彩色grep输出:不是GREP_OPTIONS不是别名


10

我想要彩色输出grep

....但是

  • 策略1:GREP_OPTIONS。但这已被弃用。参见http://www.gnu.org/software/grep/manual/html_node/Environment-Variables.html
  • 战略2:乍看之下,GREP_COLORS看起来像是解决方案,但这却有所不同。
  • 策略3:别名。这不适用于find ... | xargs grep,因为xargs不评估别名。
  • 策略4:编写一个简单的包装脚本。不,我认为这太脏了,麻烦多于解决。
  • 策略5:修补源代码
  • 策略6:联系grep开发人员,要求更换GREP_OPTIONS
  • NICE-and-EASY策略:...这是丢失的。我没有任何线索。

如何解决呢?

感谢您的帮助!

...但是我不能给赏金

骂我粗鲁,傲慢,侮辱,辱骂....

我只看到解决方法-没有解决方案。没有答案满足了这个问题。

感谢你付出的努力。


1
您已经拒绝了两个使用包装脚本(您的策略4)作为“不是真正的答案”的建议。您能描述什么是“肮脏”,“麻烦”或“不是真的答案”吗?也许这是一个可以解决的单独问题。
JigglyNaga

2
策略5修补了源代码并设置color_option2 ...
don_crissti

2
@JigglyNaga这是我的解释,为什么包装脚本不是解决方案。我们的团队管理多个服务器。目前不到一千,但数量正在增加。是的,我们使用配置管理,将脚本轻松部署到所有配置中很容易。但是我希望事情变得简单明了(想想团队中的新成员。我不想让他们感到困惑)。该--color选项已具有值auto。我只是不知道为什么默认情况下无法激活它。
guettli

您应该使用策略4或5-我希望策略4带有最少的破折号/ sh脚本(exec grep --color=auto "$@"),还可以选择使用其他名称(grepccolorgrep)。这具有可忽略的开销(并且在运行时没有额外的并发进程)。之所以将它们标记为“不够容易”,是因为您没有看到此功能足够有用,无法花费(相对较少)的一次性努力来实现它,而正在寻找其他人来为您完成它。因此,您对发布的答案的“不是真正的答案”评论是很不礼貌的。
名义动物

1
@NominalAnimal是的,您说对了,“不是一个真正的答案”听起来很粗鲁。我不是母语人士。哪种措词(传输相同的消息)会更好?
guettli

Answers:


13

OP指出选项不合适的某些原因在现实中没有根据。在这里,我将展示使用OP的策略4有什么样的效果:


在大多数发行版中,grep安装在/bin(典型)或/usr/bin(OpenSUSE,也许其他)中,并且默认PATH包含/usr/local/bin/bin或之前/usr/bin。这意味着如果您/usr/local/bin/grep使用

#!/bin/sh
exec /bin/grep --color=auto "$@"

这里/bin/sh是你的分布,通常bash或破折号提供POSIX兼容的shell。如果grep在中/usr/bin,则使

#!/bin/sh
exec /usr/bin/grep --color=auto "$@"

该脚本的开销很小。该exec语句意味着脚本解释器将被grep二进制文件替换;这意味着外壳grep程序在执行时不会保留在内存中。因此,唯一的开销是脚本解释器的一个额外执行,即挂钟时间的较小延迟。延迟大致是恒定的(仅取决于是否在页面缓存中grepsh已经在页面缓存中,以及取决于有多少I / O带宽),并且不取决于grep执行时间或处理的数据量。

那么,该延迟(即包装器脚本添加的开销)有多长时间?

要找出答案,请创建上面的脚本,然后运行

time /bin/grep --version
time /usr/local/bin/grep --version

在我的机器上,前者的实时时间为0.005s(经过大量运行),而后者的时间为0.006s。因此,在我的机器上使用包装器的开销是每次调用0.001s(或更短)。

这无关紧要。

我也看不到任何“肮脏”的东西,因为许多常见的应用程序和实用程序使用相同的方法。要在/bin和中查看您计算机上的此类列表/usr/bin,只需运行

file /bin/* /usr/bin/* | sed -ne 's/:.*shell script.*$//p'

在我的机器,上面的输出包括egrepfgrepzgrepwhich7zchromium-browserldd,和xfig,这是我经常使用。除非您将整个发行版都视为依赖包装器脚本的“肮脏”,否则您没有理由将此类包装器脚本视为“肮脏”。


对于此类包装脚本可能会导致的问题:

如果只有人类用户(而不是脚本)的用grep的版本,默认为,如果输出到终端颜色支持,则包装脚本可以被命名colorgrepcgrep或任何OP认为合适。

这样可以避免所有可能的兼容性问题,因为的行为grep完全不会改变。


grep使用包装器脚本启用选项,但要避免任何新问题:

我们可以轻松地重写包装器脚本以支持自定义,GREP_OPTS即使该脚本GREP_OPTIONS不受支持(因为它已被弃用)。这样,用户可以简单地添加export "GREP_OPTIONS=--color=auto"或类似于他们的个人资料。/usr/local/bin/grep然后

#!/bin/sh
exec /bin/grep $GREP_OPTIONS "$@"

请注意,左右没有引号$GREP_OPTIONS,因此用户可以指定多个选项。

在我的系统上,time /usr/local/bin/grep --versionGREP_OPTIONSempty或GREP_OPTIONS=--color=auto用来执行,与包装器脚本的先前版本一样快。也就是说,执行时间通常比plain花费一毫秒grep

最后一个版本是我个人推荐使用的版本。


总而言之,OP的策略4:

  • grep开发人员推荐

  • 实现起来很简单(两行)

  • 开销微不足道(在此特定笔记本电脑上每次调用额外延迟一毫秒;在每台计算机上轻松验证)

  • 可以作为添加GREP_OPTS支持的包装脚本来实现(以替换已弃用/不受支持的GREP_OPTIONS

  • 可以完全不影响脚本或现有用户的方式(作为colorgrep/ cgrep)实现

因为它是一种已经在Linux发行版中广泛使用的技术,所以它是一种常见的技术,而不是“肮脏的”。

如果实现为单独的包装器(colorgrep/ cgrep),则它不会产生新的问题,因为它根本不影响grep行为。如果将其实现为可增加GREP_OPTS支持的包装脚本,则使用GREP_OPTS=--color=auto的风险与上游添加默认风险的风险完全相同(现有脚本存在写入问题)--color=auto。因此,这种“造成的问题多于解决的问题”的说法是完全错误的:没有创建其他问题。


3

您提供的第一个策略文档说明:

请改用别名或脚本。例如,如果grep在目录“ / usr / bin”中,则可以在$ HOME / bin之前添加PATH并创建包含以下内容的可执行脚本$ HOME / bin / grep:

#! /bin/sh
export PATH=/usr/bin
exec grep --color=auto --devices=skip "$@"

因此,如果您无法使用别名,则包装脚本是唯一的方法。


这就是策略4 ...并非真正的答案。
guettli

3

GREP_OPTIONS不建议使用该变量的原因是,当grep在脚本中的某个位置调用该变量时,它往往会引起问题,并且该脚本无法与该变量的替代选项一起使用。如果为编写包装脚本,grep除非您使用不同的名称否则您将遇到同样的问题。

$ cat ~/bin/cgrep
#!/bin/sh
exec grep --color=always "$@"
$ find  -exec cgrep  {} +

或者,将您喜欢的选项存储在变量中。在zsh以外的shell中,如果选项包含通配符(\[*?),则很麻烦,但否则,您可以仅使用unquoted变量来获取带有参数的命令。

cgrep=(grep --color=always)
find  -exec $cgrep  {} +

请注意,GNU和BSD grep可以递归处理目录树,从而减少了大多数情况下find与之结合的需要grep


1
这就是策略4 ...并非真正的答案。
guettli

@guettli,这是正确的答案。如果要使用具有不同行为grep的命令,则需要使用其他名称的命令,否则,如果保持相同的名称,则会破坏期望原始/标准行为的脚本。那是最干净的,不会造成额外的麻烦
斯特凡Chazelas

@StéphaneChazelas是的,你是对的。根据您的观点,这是正确的答案。
guettli

1

最简单的方法是使用别名(策略3)。如果您确实在乎该xargs命令,仍然可以使用bash函数覆盖它。

alias grep='grep --color'
xargs() {
    local args
    for ((i=1; i<=$#; i++))
    do
            if [[ "-E -L -P -I -s -d" == *"${!i}"* ]]; then
                    ((i=i+1))
            elif [[ ${!i:0:1} != "-" ]]; then
                    if [[ ${!i} == "grep" ]]; then
                            args="--color"
                    fi
                    /usr/bin/xargs ${@:1:i} $args ${@:i+1}
                    return;
            fi
    done
}

但这并不比使用包装程序命令好,这似乎是grep团队推荐的解决方案:

/usr/local/bin/grep:

#!/bin/bash
/bin/grep --color "$@"

以我的拙见,您应该与grep开发人员团队联系,要求他们提供对GREP_OPTIONS变量的简单替换,以grep根据某种环境变量启用颜色。

对于他们来说,默认情况下启用该color选项或设置该选项将非常简单GREP_COLORS


1
感谢您“ ...您应该与grep开发人员团队联系...”。这给了我积极的反馈。现在我知道,我并不是唯一认为这里缺少某些东西的人。
guettli

我在问题中添加了您的评论“ ...您应该联系grep开发人员团队...”作为对策6。到目前为止,这是我最喜欢的答案。
guettli

0

这是@NominalAnimal给出的最高答案的解决方案,但通常grep: ...使用警告(而不是/bin/grep: ...):

#!/bin/bash
exec -a grep /bin/grep --color=auto "$@"

我知道如何编写包装器。在这种情况下,包装器不是解决方案。
盖特利

@guettli好吧,答案并不是要精确解决您的情况……如果注释的格式设置与答案相同,那将是注释。(而且我曾因原作者的意图而拒绝了类似的编辑。)至于您的情况,我认为对您的问题的正确字面回答是:不存在另一种“策略易而易行的策略”。
基里尔·布林金
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.