如何使 grep 输出适合屏幕的字符宽度

如何使 grep 输出适合屏幕的字符宽度

我经常会用很长的行来 grep 文件,从而导致一个匹配单词的输出相当于一页。

将输出限制为仅与终端宽度相同的字符的好方法是什么?

我意识到这意味着匹配的词可能不在队列中。但我仍然想要上下文,所以仅文件名是不可接受的。

答案1

考虑这个包装函数,它将任何参数传递给 grep,然后将输出剪切到 $COLUMNS (或 80,如果未设置 COLUMNS):

function grepcut() {
  grep "$@" | cut -c1-${COLUMNS:-80}
}

像这样使用它:

$ grepcut sometext somefiles

或者

$ set | grepcut LS_COLORS

答案2

这是一种更复杂的方法,可以提供您可能更喜欢的输出。如果您通常搜索简单字符串(没有正则表达式特殊字符)并且不使用任何选项(或者至少使用相同的选项),那么它的效果最好每一个时间)。我的greptrim脚本:

#!/bin/bash
case "$1" in
    ("")
        echo "Usage: $0 string [files...]"
        exit 2
        ;;
    (-*)
        echo "This script can't take options."
        exit 2
        ;;
esac
read rows cols <<< $(stty size)
if [ "$cols" = "" ]
then
        cols=80
fi
margin=$(( (cols-${#1}) / 2 ))
grep -o ".\{,$margin\}$1.\{,$margin\}" "${@:2}"
  • 准备工作:检查是否存在非空字符串(模式)参数,并且它不是一个选项。
  • 然后我们使用另一种方法来获取列数。1
  • 从屏幕的宽度(列数)中减去字符串参数的宽度 ( ${#1},然后除以二。这将计算字符串左侧和右侧可以拥有的字符数,并且该行仍然适合例如,对于 80 列屏幕上的 10 个字符的字符串, margin将为 35(因为 35+10+35=80)。
  • 最终的命令看起来有点像grep -o "$@",但我们确实如此grep -o "$1" "${@:2}"。  "${@:2}"是一个bashism,意思是,但从(如果有的话)"$@"开始。$2
  • 我们$1.\{,$margin\}- 例如.\{,35\}- 前后包裹起来。这最多可匹配 35 个任何字符,因此,我们的模式总共最多可匹配 80 个字符,原始模式$1位于中间。
  • -o意味着只输出匹配的文本——所以我们每行最多输出 80 个字符。

我使用了这个示例文本:

Once upon a midnight dreary, while I pondered, weak and weary, Over many a quaint and curious volume of forgotten lore—
While I nodded, nearly napping, suddenly there came a tapping, As of some one gently rapping, rapping at my chamber door.
“’Tis some visitor,” I muttered, “tapping at my chamber door— Only this and nothing more.”

下面是在 80 列屏幕中运行的示例:

$ ./greptrim or raven.txt
r many a quaint and curious volume of forgotten lore—
ently rapping, rapping at my chamber door.
“’Tis some visitor,” I muttered, “tapping at my chamber d
oor— Only this and nothing more.”

请注意,字符串“or”在这节经文中出现了六次:“f或者得到”,“我或者e”、“做或者“, “访问或者“, “做或者”和“米或者e”。请注意,我们两次获得输入的第三行,因为“访问或者”和“做或者” 相距超过 39 个字符。

更多注意事项:

  • 显然,该脚本可以扩展以处理选项。弄清楚哪个参数是模式以及哪个参数是文件名变得很棘手。
  • 如果您总是想使用某些选项,例如-i,只需将其添加到grep脚本中的命令中即可。
  • 如果相加-n,则应减去 4 或 5 cols
  • 您可以使用比简单字符串更复杂的模式的脚本,但结果可能不令人满意,因为短正则表达式可以匹配长文本段(反之亦然),因此 的计算margin将是错误的,您可能会每行多于(或少于)80 个字符。
  • 如果添加-E,则必须将边距正则表达式更改为.{,$margin}(删除反斜杠)。
  • 一个可选功能是将最后一行更改为

    grep -o ".\{,$margin\}$1.\{,$margin\}" "${@:2}" | grep --color=auto "$1"
    

    突出显示搜索字符串:

          相同的输出,但有颜色

    请注意,“遗忘”中的“或”与“门”中的“或”完全一致。对于margin从行首开始出现的字符数多于字符的字符串,通常会发生这种情况。

_______
1我是cols这样的 ( read rows cols <<< $(stty size))

  1. 展示不同的做法,并且
  2. 因为我正在使用 Cygwin,但tput尚未安装,也COLUMNS未设置。

它符合 POSIX 标准。

相关内容