如何仅对 bash 脚本的某些关键字进行着色?

如何仅对 bash 脚本的某些关键字进行着色?

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

在本例中,关键字是“PASS”和“FAIL”。

如何将“PASS”着色为绿色,将“FAIL”着色为红色?

答案1

supercat似乎正在做你正在寻找的事情。

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

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

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

最后,GNUgrep可用于突出显示模式 - 但只能使用一种颜色(即,不能将 PASS 设为绿色,将 FAIL 设为红色,两者都将用相同的颜色突出显示)。

通过这样的方式传输数据:

grep -E --color "\b(PASS|FAIL)\b|$"

此示例使用 的grep扩展-E正则表达式选项,但也可以使用-G基本正则表达式、-F固定字符串和PCRE。-P

所有匹配项都会突出显示。默认为红色,或设置 GREP_COLOR 环境变量。

这项工作的关键是|$模式中的结尾与行尾匹配(即所有行都匹配),因此所有行都将显示(但不着色)。

它们\b是单词边界标记,因此它匹配例如 FAIL 但不匹配 FAILURE。它们不是必需的,因此如果您想匹配部分单词,请删除它们。

这是我昨天编写的 supercat 的示例包装脚本。它有效,但在编写它时,我发现 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"

答案2

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

#! /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

答案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

答案4

如果您愿意安装 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.*'

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

相关内容