如何只为bash脚本着色一些关键字?


10

我正在运行一些单元测试代码。单元测试代码输出常规文本。文本很多,因此我想为用户突出显示重要的关键字。

在这种情况下,关键字为“通过”和“失败”。

您如何将“通过”着色为绿色,将“失败”着色为红色?


您是否考虑过限制通过的测试的stdout / stderr,并且仅打印失败的测试的stdout / stderr?PHPUnit可以执行此操作,也可以将其配置为执行此操作。我发现这种方法效果很好,YMMV。
克莱顿·史丹利

Answers:


8

supercat 似乎可以满足您的需求。

包装:超级猫
Description-zh:为终端和HTML着色文本的程序
 Supercat是一个程序,可根据匹配的常规字符为文本着色
 表达式/字符串/字符。Supercat也支持html输出
 作为标准ASCII文本。与某些文本着色程序不同
 存在,Supercat不需要您必须是程序员才能
 制定着色规则。
主页:http://supercat.nosredna.net/

似乎没有任何方法可以在命令行上告诉它要着色的颜色,您必须指定一个配置文件。

我似乎还记得,曾经有一个名为“ hilite”或“ hl”的程序来突出显示与模式匹配的文本(例如grep --colour,但也显示不匹配的行),但是当我搜索它时却找不到。

最后,grep可以使用GNU 突出显示图案-但只能使用一种颜色(即,不能将PASS设置为绿色,将FAIL设置为红色,将两个颜色都用相同的颜色突出显示)。

通过以下方式传送数据:

egrep --color "\b(PASS|FAIL)\b|$"

这个示例使用egrep(aka grep -E),但是-G基本的regexp,-F固定字符串和-PPCRE也可以使用。

所有比赛都将突出显示。默认为红色,或设置GREP_COLOR环境变量。

这项工作的关键是|$图案中的最后一个与行尾匹配(即所有行都匹配),因此将显示所有行(但不着色)。

\b都是字界碑以便它匹配如失败,但不是失败。它们不是必需的,因此,如果要匹配部分单词,请将其删除。

这是我昨天编写的超级猫包装脚本示例。它有效,但是在编写时,我发现supercat对于区分大小写的搜索没有任何选择。IMO,这使该程序的实用性大大降低。但是,它确实大大简化了脚本,因为我不必编写'-i'选项:)

#! /bin/bash 

# Requires: tempfile from debian-utils, getopt from util-linux, and supercat

SCRIPTNAME=$(basename $0)
CFGFILE=$(tempfile -p spc)

usage() {
  cat <<__EOF__
Highlight regexp patterns found on stdin or files specified on command
line with specified colours.

Usage: $SCRIPTNAME [ --colour "pattern" ...] [FILE]

Options:

        -k,--black   regexp
        -r,--red     regexp
        -g,--green   regexp
        -y,--yellow  regexp
        -b,--blue    regexp
        -m,--magenta regexp
        -c,--cyan    regexp
        -w,--white   regexp

Example:

    run-script.sh | $SCRIPTNAME --green PASS --red FAIL

__EOF__
  exit 0
}


# Format definition from the spc man page:
#1234567890123456789012345678901234567890123456789012345
#HTML Color Name      Col A N T RE / String / Characters
FMT="%-20s %3s %1s %1s %1s (%s)\n"

add_color_to_config() {
  COLOR="$1"
  PATTERN="$2"

  printf "$FMT" "$COLOR" "$COLOR" - 0 r "$PATTERN" >> "$CFGFILE"
}


# uses the "getopt" program from util-linux, which supports long
# options. The "getopts" built-in to bash does not.
TEMP=$(getopt \
       -o 'hk:r:g:y:b:m:c:w:' \
       -l 'help,black:,red:,green:,yellow:,blue:,magenta:,cyan:,white:' \
       -n "$0" -- "$@")

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

eval set -- "$TEMP"

while true ; do
    case "$1" in
        -k|--bla*)       add_color_to_config blk "$2" ; shift 2 ;;
        -r|--red)        add_color_to_config red "$2" ; shift 2 ;;
        -g|--gre*)       add_color_to_config grn "$2" ; shift 2 ;;
        -y|--yel*)       add_color_to_config yel "$2" ; shift 2 ;;
        -b|--blu*)       add_color_to_config blu "$2" ; shift 2 ;;
        -m|--mag*)       add_color_to_config mag "$2" ; shift 2 ;;
        -c|--cya*)       add_color_to_config cya "$2" ; shift 2 ;;
        -w|--whi*)       add_color_to_config whi "$2" ; shift 2 ;;

        -h|--hel*)       usage ; exit 0 ;;

        --)         shift ; break ;;

        *)          echo 'Unknown option!' ; exit 1 ;;
    esac
done

spc -R -c "$CFGFILE" "$@"
rm -f "$CFGFILE"

1
顺便说一句,如果您使用过,则supercat可以修改发布的脚本,以基于命令行args生成临时配置文件,然后调用spc -c /path/to/your/temp/config。这将使您可以轻松地在命令行上为不同的样式指定不同的颜色。
cas 2012年

顺便说一句,我写了一个简单的包装脚本来做到这一点。我现在必须去上班,但是我要清理一下,添加一些评论,等等,然后在今天晚些时候发布。
cas 2012年

5

这是一个彩色的正则表达式模式通用脚本(可能需要进行一些修饰):

#! /bin/bash

color_to_num () {
  case $1 in
    black)  echo 0;;
    red)    echo 1;;
    green)  echo 2;;
    yellow) echo 3;;
    blue)   echo 4;;
    purple) echo 5;;
    cyan)   echo 6;;
    white)  echo 7;;
    *)      echo 0;;
  esac
}

# default values for foreground and background colors
bg=
fg=
bold="$(tput bold)"
italics=""
boundary=""

while getopts f:b:sli option; do
  case "$option" in
    f) fg="$OPTARG";;
    b) bg="$OPTARG";;
    s) bold="";;
    l) boundary=".*";;
    i) italics="$(tput sitm)";;
  esac
done

shift $(($OPTIND - 1))

pattern="$*"

if [ -n "$fg" ]; then
  fg=$(tput setaf $(color_to_num $fg))
fi
if [ -n "$bg" ]; then
  bg=$(tput setab $(color_to_num $bg))
fi

if [ -z "$fg$bg" ]; then
  fg=$(tput smso)
fi

sed "s/${boundary}${pattern}${boundary}/${bold}${italics}${fg}${bg}&$(tput sgr0)/g"

命名hilite.sh并以这种方式使用:

$ ./BIN_PROGRAM | hilite.sh -f green PASS | hilite.sh -f red FAIL

$ # Here is an example one liner
$ echo -e "line 1: PASS\nline 2: FAIL" | hilite.sh -f green PASS | hilite.sh -f red FAIL

我这样做community wiki是因为我的解决方案不起作用。
Trevor Boyd Smith

一种简单的测试方法是制作另一个脚本,该脚本回显带有关键字“ PASS”和“ FAIL”的文本。然后,该脚本将调用它。
Trevor Boyd Smith

稍微偏离主题,但我必须指出,将$BINvia 的输出解析eval为命令替换可能很脆弱,麻烦且非常危险。STDOUT是一个流,通常是指像工具一样由流处理。尝试在变量中捕获整个流不是很有效。另外,它eval非常危险,因此,只有在您真正知道自己在做什么的情况下,才使用它。
jw013

我用工作正常的脚本替换了脚本。
安格斯

@angus,真的非常好,令人印象深刻的脚本IMO。
Trevor Boyd Smith

3

将任意字符串(如tput输出)嵌入到sed替换表达式中是有问题的,因为您必须确保(通过转义)字符串是有效的sed语法,最好避免这种复杂性。我会awk改用。举个例子:

{ echo line 1: PASS; echo line 2: FAIL; } | 
    awk -v "red=$(tput setaf 1)" -v "green=$(tput setaf 2)" \
        -v "reset=$(tput sgr0)" '
    { for (i = 1; i <= NF; i++) {
           if ($i == "FAIL") printf "%s", red "FAIL" reset;
           else if ($i == "PASS") printf "%s", green "PASS" reset;
           else printf "%s", $i

           if (i == NF) printf "%s", ORS
           else printf "%s", OFS 
      }}'

关键是将tput序列分配给awk变量,此处使用-v选项完成。


我运行了您的程序,它可以完成所需的工作。头晕!但是不幸的是我不是一个高手,所以我很难理解发生了什么。在错误的地方纠正我。对于每个新行,awk是否运行?awk源代码中的for循环正在执行:“对于该行中的所有令牌”?然后处理每个令牌?
Trevor Boyd Smith

Awk根据字段和记录进行思考。默认情况下,记录是文本行,而字段是非空格。一个awk脚本由一组块(在之间的东西的{}顶部电平)。每个块都与一个条件相关联-在我上面的文章中没有任何内容,因为我想无条件地对每个输入行进行操作。Awk的操作方式是从文件或标准输入中读取记录(在这种情况下为STDIN b / c,未提供文件名),然后将它们与每个块按顺序进行匹配,如果条件匹配,则在记录上执行该块。
2012年

2

使用printf:

printf "\e[%sm%s\e[00m\n" <some_number> <text_in_colour>

例如。

printf "\e[%sm%s\e[00m\n" 32 yodle

最后\n添加换行符。

查看类似的可能值:

for i in {0..9} {30..38} {90..98} {100..108};
do
    printf "%d:\e[%sm%s\e[00m\n" $i "$i" yodle;
done

除颜色外,您还可以通过组合数字来添加粗体,下划线或带有彩色背景的彩色文本等修饰符。要创建带有灰色背景并带有下划线和删除标记的蓝色文本,请执行以下操作:

printf "\e[%sm%s\e[00m\n" "4;9;34;107" yodle

干杯,

/ B2S


2

如果您愿意安装BASH脚本和ack,则该hhlighter软件包具有有用的默认颜色和简单的界面https://github.com/paoloantinori/hhighlighter

重点示例

您可以像这样使用它来突出显示以FAIL:开头的行:

h -i 'FAIL.*'

或包含FAIL

h -i '.*FAIL.*'

或用于各种常见日志条目:

h -i '.*FAIL.*' '.*PASS.*' '.*WARN.*'

当然,对于使用普通grep的单色(红色):

$ printf 'Pass: good job\nFail: bad job\n' | grep -Ei --colour=auto '^|fail.*'

^每一行相匹配,但它是一个特殊的匹配,并打印整条生产线。要突出显示的表达式在后面定义|。只要用分隔,可以添加更多表达式|

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.