Grep

帶有突出顯示模式的彩色 grep 輸出

  • January 24, 2020

我確實有以下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個解決方案!!以下所有建議都有效,它們有細微的差異,但它們確實回答了這個問題。我選擇了一個突出所有出現的模式,幾乎是一條線,但老實說選擇是困難的,因為它們是相當的……

**編輯——**希望對此進行改進:查找結果在分析之前不會被阻塞,即輸出被刷新並每行處理。這可能嗎?

也許是這樣的?

在此處輸入圖像描述

命令:

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部分。

您可以使用zsh’s 的內置 glob 運算符來做到這一點。這將有幾個好處:

  • 輕鬆解決此問題
  • 使用包含換行符的路徑名
  • 使僅在基本名稱中突出顯示模式變得容易
  • 使用萬用字元(在您的方法中,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)

引用自:https://unix.stackexchange.com/questions/563041