Grep 在多个匹配上失败

Rei*_*ica 4 grep

我想 grep 一种搜索模式,但只有在只有一个唯一匹配项时才会成功(并输出匹配行)。如果两行匹配,grep 应该失败或不输出任何内容。

ter*_*don 7

您不能使用 来执行此操作grep,但您可以简单地计算匹配数。我不知道grep您正在使用什么 shell、什么或什么操作系统,但这里有一个可以执行此操作的 bash 函数的示例:

\n
maxOne() (\n    pattern="$1"\n    file="$2"\n    IFS=$\'\\n\'\n    set -f\n\n    results=( $(grep -m2 -- "$pattern" "$file") )\n    if [ "${#results[@]}" -eq 1 ]; then\n        printf -- \'%s\\n\' "${results[@]}"\n        return 0\n    else\n        return 1\n    fi\n)\n
Run Code Online (Sandbox Code Playgroud)\n

将这些行添加到您的文件中~/.bashrc,或者只是将它们粘贴到正在运行的 bash 会话的终端中,然后您可以执行以下操作:

\n
maxOne foo file\n
Run Code Online (Sandbox Code Playgroud)\n

foo在 中搜索file。请注意,-m此处使用的选项(最大结果)是为了提高grep在两场比赛后退出的效率,并非所有版本都支持,grep因此如果它给您带来错误,只需将其删除即可。这不是必需的,它只是加快速度。

\n

重要提示:这不适用于多行搜索字符串,grep -z如果您grep支持的话,您可以使用多行搜索字符串。如果您需要能够处理多行搜索模式,则需要不同的方法。此外,这不适用于匹配空行的模式(例如grep \'^$\' file)。St\xc3\xa9phane\ 的解决方案将处理空行,因此如果这是一个问题,这将是一个更好的选择。与我不同的是,他还可以处理多个文件,这是一个很好的福利。

\n


Sté*_*las 6

你可以这样做:

unique_egrep() (
  export ERE="$1"; shift
  exec gawk -e '
    BEGIN               {ret = 1}
    BEGINFILE           {n = 0}
    $0 ~ ENVIRON["ERE"] {if (n++) nextfile; found = $0}
    ENDFILE             {if (n == 1) {print FILENAME":"found; ret = 0}}
    END                 {exit ret}' -E /dev/null "$@"
)
Run Code Online (Sandbox Code Playgroud)

unique_egrep pattern *.txt比如。

这里使用-e 'code' -E /dev/null(代替'code')技巧来处理任意文件路径。

所有-e-EBEGINFILE和都是 GNU 扩展(尽管现在也在许多其他实现中找到)ENDFILEnextfilenextfile

  • @user000001,请参阅[如果文件名包含 =,awk 为何停止并等待以及如何解决该问题?](//unix.stackexchange.com/a/490535) (2认同)