带有突出显示模式的彩色 grep 输出

带有突出显示模式的彩色 grep 输出

我确实有以下find-file脚本:

find . -type f -iname "*$1*" -printf '%P\n' \
| GREP_COLORS="sl=0;33;49:ms=1;34;49" grep --color=always '^\|[^/]*$' \
| grep -i --color=auto "$1"

它的作用是:

  • 给路径部分着色
  • 对基本名称部分中的图案进行着色

在此输入图像描述

问题:图案后,颜色被重置

对于基本名称部分,它可以是完全白色的,这可以解决问题(尽管我没有找到改变它的方法)。

对于路径部分,它仍然是一个问题,正如您在上面的屏幕截图中所看到的:颜色被重置,因此我们再也看不到文件路径真正结束的地方!

有针对这个的解决方法吗?

编辑 - 有3个解决方案!以下所有建议都有效,它们有轻微的差异,但它们确实回答了问题。我选择了一个突出显示所有出现的模式的选项,并且几乎是一行,但老实说选择很困难,因为它们相当相同......

编辑 - 人们希望对此进行改进:在分析之前,查找结果不会被阻塞,也就是说,输出会被逐行刷新和处理。这可能吗?

答案1

也许是这样的?

在此输入图像描述

命令:

pattern='oRg'; find . -type f -iname "*$pattern*" -printf '%P\n' \
| GREP_COLORS="sl=0;33:mt=1;34" grep --color=always '[^/]*$' \
| GREP_COLORS="sl=1;34" grep --color=always -iP "$pattern(?=[^/]*$)" \
| GREP_COLORS="sl=0;33" grep -i "$pattern" --color

如果您不想突出显示,请删除最后一行图案部分dirname

查看grep的环境变量GREP_COLORS部分了解详细信息。

答案2

zsh您可以使用的内置全局运算符来完成此操作。这将有几个好处:

  • 轻松解决这个问题
  • 使用包含换行符的路径名
  • 可以轻松地仅突出显示基本名称中的模式
  • 使用通配符(在您的方法中,findgrep以不同的方式解释模式)
  • 给你一个排序列表
  • 甚至可以在非 GNU 系统上工作(-printf-iname--color都是非标准扩展)。

也许是这样的:

#! /bin/zsh -
pattern="(#i)${1?Please specify a pattern}"

set -o extendedglob

typeset -A find_file_color
find_file_color=(
  dirname  $'\e[0;33;49m'
  basename $'\e[1;34;49m'
  match    $'\e[1;33;44m'
  reset    $'\e[m'
)

colorize_file() {
  local file=${1-$REPLY}
  case $file in
    (*/*)
      REPLY=$find_file_color[dirname]$file:h$find_file_color[reset]/;;
    (*)
      REPLY=
  esac
  REPLY+=$find_file_color[basename]${${file:t}//(#m)$~pattern/$find_file_color[match]$MATCH$find_file_color[basename]}$find_file_color[reset]
}

print -rC1 -- **/*$~pattern*(ND.+colorize_file)

print请注意,它会在传递到打印之前构建整个列表并对其进行排序。因此,只有找到所有文件后,您才会开始获得一些输出。要在找到它们时打印它们(但随后我们需要放弃排序),您可以让 glob 限定符函数打印彩色文件:

#! /bin/zsh -
pattern="(#i)${1?Please specify a pattern}"

set -o extendedglob

typeset -A find_file_color
find_file_color=(
  dirname  $'\e[0;33;49m'
  basename $'\e[1;34;49m'
  match    $'\e[1;33;44m'
  reset    $'\e[m'
)

colorize_file() {
  local file=${1-$REPLY}
  case $file in
    (*/*)
      REPLY=$find_file_color[dirname]$file:h$find_file_color[reset]/;;
    (*)
      REPLY=
  esac
  REPLY+=$find_file_color[basename]${${file:t}//(#m)$~pattern/$find_file_color[match]$MATCH$find_file_color[basename]}$find_file_color[reset]
  print -r -- $REPLY
  false # don't bother adding the file to the glob expansion
}

: **/*$~pattern*(ND.+colorize_file)

答案3

1)如何为文本着色的示例

# creation of 3 escape sequences
C_1=$(echo -ne "\033[30;47m" ) ;
C_2=$(echo -ne "\033[32;41m" ) ;
C_3=$(echo -ne "\033[37;44m" ) ;
C_N=$(echo -ne "\033[0m"  )  ;

#simple example for using it
echo $C_1 Hello in C_1 $C_N normal ;
echo $C_2 Hello in C_2 $C_N normal ;
echo $C_3 Hello in C_3 $C_N normal ;

值的解释在这里: https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit

在您的情况下,因为您正在寻找简单的模式,所以我只能使用一个 sed 命令。

PAT="tot" ; 
find ./ -iname  \*$PAT\*  -printf '%P\n' | \
    sed "s/^\(.*\/\)\{0,1\}\([^\/]*\)\($PAT\)\([^\/]*\)\$/${C_1}\1${C_2}\2${C_3}\3${C_N}\4/i"

\1 is the full path ending with the last /
\2 is the pattern of the filename before the pattern
\3 is the pattern
\4 is after the pattern

相关内容