【问题标题】:Exclude word from grep when using context flags?使用上下文标志时从 grep 中排除单词?
【发布时间】:2019-12-04 17:30:31
【问题描述】:

有没有办法从grep 结果中删除不需要的行,这与显示上下文(-A-B)、着色匹配项(--color)或显示文件名和行不冲突数字(-nH)?

考虑例如grepping 一个复杂的多文件编译日志,查看针对alpha.o 而不是针对beta.o 编译的文件。如果我只想要没有任何其他功能的线条,我可以做类似的事情

find -name "make.log" -exec grep 'alpha.o' {} \; | grep -v 'beta.o'

有没有机会应用类似的过滤器

find -name "make.log" -exec grep --color -A 3 -B 3 -nH 'alpha.o' {} \;

最小的工作示例。

这是一个玩具示例,因为实际示例是企业产品。我想不出一个很好的方法来在这里提供一个足够大的现实示例。

# Reproducible random file.
# -- example.bash --

mkdir -p /tmp/foo
cd /tmp/foo
RANDOM=0 # Seed it.
for ((i=0;i<10000;i++)); do
    printf ' %04x%04x' $RANDOM $RANDOM $RANDOM $RANDOM
    if (($RANDOM % 100 > 1)); then 
        printf ' 0a00%04x' $RANDOM
    else
        printf ' %04x%04x' $RANDOM $RANDOM
    fi
    printf ' %04x%04x' $RANDOM $RANDOM $RANDOM $RANDOM
    printf '\n'
done | split -l 1000 - data.

假设我想要所有以0a 开头的数字的行。

>>> grep '\b0a' /tmp/foo/data.* | head
/tmp/foo/data.aa: 6b883baf 6aae6938 000000 0a006f96 0f0c1675 71d417cd
/tmp/foo/data.aa: 2ba4446a 21070bd0 000001 0a007681 465322a8 54e20231
/tmp/foo/data.aa: 7bc17b37 2d493c77 000002 0a006c68 30a96b30 735456a8
/tmp/foo/data.aa: 4f707722 7d5d1b6f 000003 0a002602 7801346c 7285394a
/tmp/foo/data.aa: 49a60fcf 38e90f7d 000004 0a007c69 14e11a16 7549690e
... (and 9000 more lines) ...

我注意到有一个以“0a00”开头的列的重复模式。让我们看看有没有更有趣的模式。

>>> grep -n '\b0a' /tmp/foo/data.* | grep -v '\b0a00'
/tmp/foo/data.aa:607: 21c1631c 09fd779d 37435823 12873910 0aa64882
/tmp/foo/data.aa:759: 1d213f2c 0ac76099 5c0719c5 26c1265c 30db2bc3
/tmp/foo/data.ab:677: 09b2512f 0ac0772e 5e9156f6 6f396505 5e027e02
/tmp/foo/data.ad:102: 1a191fad 582104da 4cdd7c5c 3d624820 0aa863fa
/tmp/foo/data.af:556: 559b7651 0a6c0a34 34612ac1 29567c5c 2f62187f
...

为了便于查看,添加着色可能会更好。但是由于 ansi 转义序列,这违反了过滤规则!

事情从这里开始变得奇怪。作为一种解决方法,我们可能会在事后重新添加突出显示,但它不会为文件/行号列着色。

同样,使用-A-B 添加上下文也需要付出努力。例如。 grep -n -A 3 '\b0a' /tmp/foo/data.* | grep -v '\b0a00' 会给出不满意的结果,因为它不知道上下文行。

同样,文件名和行号部分可能会导致问题。例如,当输出包含文件名时,我们可能希望排除搜索字符串位于行首 (grep -v '^PATTERN') 的行,这很难做到。

因此,将 grep 结果传递给 grep -v 会很快导致糟糕的可维护性和过于复杂的结构。

【问题讨论】:

  • 听上去是个好问题,赞成。但是,您仍然应该添加一些我们可以处理的示例
  • 添加一些测试数据,我懒得自己创建了。并且,在提问时尽量遵守MCVE 标准
  • @Thor 添加了一些示例。我最初没有,因为我可以上传的任何东西都是一个远离真实应用程序的玩具示例。我遇到的所有案例要么在隐私方面存在问题(例如从 Keepass 过滤数据),要么属于商业机密法规,或者只是太大而无法在此处发布。

标签: grep


【解决方案1】:

我看到了两种方法:

  1. 保留转义序列并将它们包含在您的模式中
  2. 后突出显示文本

在你的模式中包含转义序列

以下是适用于此的示例。您可能需要调整要匹配的转义序列:

# Define the coloring reset sequence
rst=$'\x1b\\\[m\x1b\\\[K'
grep --color=always -n '\b0a' /tmp/foo/data.* | grep -vE "0a${rst}00"

输出:

/tmp/foo/data.aa:39: 4d633499 398a4f7a 0a935cbd 2c4f2c3a 154f7a91
/tmp/foo/data.ab:178: 0a1300b0 2ad5117e 572b548e 68040659 5dee37bf
/tmp/foo/data.ab:636: 02e05497 0cfe1378 0ab90ea2 36aa7fb2 0ee64bbb
/tmp/foo/data.ac:369: 3e1173bd 0a2b4bb0 075d7b29 53336401 30407990
/tmp/foo/data.ac:578: 00f22d00 0a826912 79b16c04 27ab7fbb 02085f85
/tmp/foo/data.ac:690: 44847461 12384d93 6f35227c 2a1f1421 0a68356f
/tmp/foo/data.ad:27: 07443f46 3a59377e 2fb731a6 31996a1e 0aab0e69
/tmp/foo/data.aj:158: 3c90509b 0a5e5803 3e8d50cd 7e89059d 292b723f

事后强调

这是一个如何使用highlight 的示例:

将此文件保存到 langDefs 目录下(有改进的余地):

grep.lang

Description="Grep"

Digits=[[ [:-]\d+[:-] ]]

Keywords={
  { Id=1,
    Regex=[[^[^:-]+]],
  },
  { Id=2,
    Regex=[[ ^--$ ]],
  },
}

您现在可以执行以下操作:

grep -n -A3 '\b0a' /tmp/foo/data.* | grep -vE '0a00' | highlight -S grep -O ansi

【讨论】:

    【解决方案2】:

    我发现最简单的方法可能是反转逻辑,并应用排除模式首先

    示例

    例如对于问题中的示例,而不是grep -n '\b0a' /tmp/foo/data.* | grep -v '\b0a00' 可以做

    >>> grep --color=always -nH -v '\b0a00' /tmp/foo/data.* | grep --color '\b0a'
    #                |
    #                 ` Without 'always' color wouldn't be applied 
    #                   when piping the result.
    

    并接收全彩色输出:

    同样的方法适用于-A-B

    专业版

    • 不需要可能未在给定系统上安装的工具。

    反对

    • 匹配行 (FILENAME:000: ...) 和上下文行 (FILENAME-000- ...) 之间的区别消失了。
    • 数字/名称前缀使得对“行首”模式的 grepping 仍然很尴尬。而不是^foo 一个必须grep 为^.*?:.*?: foo。即使这样也不能很好地使用“颜色”解决方案,这可以通过使用Thor's answer 中描述的后处理着色来解决。但随后我们又开始安装其他工具。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      相关资源
      最近更新 更多