Bash 函数根据字符串输入匹配正则表达式进行着色

Bash 函数根据字符串输入匹配正则表达式进行着色

我有一个多行字符串,用于在 bash 脚本中打印。

docstring="
 Headings
  -H, -H CNT, -H=CNT, -HCNT, --heading CNT, --heading=CNT

 Warnings
  -W, -W CNT, -W=CNT, -WCNT, --warning CNT, --warning=CNT

 Errors
  -E, -E CNT, -E=CNT, -ECNT, --error CNT, --error=CNT"

echo "$docstring"

我想创建一个函数,它接受这个字符串并以颜色打印以-or开头的行{-

因此,下面的内容将被着色

-H, -H CNT, -H=CNT, -HCNT, --heading CNT, --heading=CNT
-W, -W CNT, -W=CNT, -WCNT, --warning CNT, --warning=CNT
-E, -E CNT, -E=CNT, -ECNT, --error CNT, --error=CNT

答案1

使用 GNU 的一种方法,假设字符串不包含\, `,"也不$包含字符:

printred(){ 
    sed -E 's/^ *\{?-.*/tput setaf 1;printf "%s" "&";tput sgr0/e' <<< "$@"
}

用法:

printred "$docstring"

要选择其他颜色,请检查:

for i in {0..7}; do
    tput setaf "$i"
    echo "tput setaf $i"
    tput sgr0
done

注意事项:

不要按原样用作 CGI 脚本,请将其保留为私有,因为正如 Stephane Chazelas 所指出的,您可以运行任意命令。这是为了在受信任的环境中使用。或者制作一种过滤器来清理输入字符串

答案2

与 GNU 实现grep或兼容:

grep --color -Ee '^\s*\{?-.*' -e '^' <<< "$docstring"

这是grepping 以任意数量的空白字符开头的行,后跟一个可选字符,{后跟-任意数量的字符,或者只是行的开头,只要输出到达终端设备(假设它显示),就会对匹配的内容进行着色在终端上,解释这些转义序列的那些)。--color=always即使输出未发送到终端设备,也可以更改为添加着色。

使用哪些属性和颜色(默认为粗体红色)是通过$GREP_COLORS环境变量(以前的$GREP_COLOR)控制的。

grep例如,GREP_COLORS='mt=1;41;33' grep...m附加的分机调用t为粗体、黄色前景、红色背景。

printred以红色打印匹配行的函数可能如下所示:

println() { # prints each of its arguments on separate lines
  [ "$#" -eq 0 ] || printf '%s\n' "$@"
}
printred() {
  println "$@" |
    GREP_COLORS='mt=31' grep --color -Ee '^\s*\{?-.*' -e '^'
}

另一种不依赖 GNUisms 来突出显示这些行的方法是sed在匹配行周围添加 ANSI 转义序列:

ESC=$(printf '\33')
printred() {
  if [ -t 1 ]; then
    println "$@" |
      sed "s/^[[:space:]]*{\{0,1\}-.*/${ESC}[31m&${ESC}[m"
  else
    println "$@"
}

或者perl代替sed

perl -pe 's/^\s*\{?-.*/\e[31m$&\e[m/'

相关内容