我想 grep 一种搜索模式,但只有在只有一个唯一匹配项时才会成功(并输出匹配行)。如果两行匹配,grep 应该失败或不输出任何内容。
答案1
您不能使用 来执行此操作grep
,但您可以简单地计算匹配数。我不知道grep
您使用的是什么 shell、什么或什么操作系统,但这里有一个可以执行此操作的 bash 函数的示例:
maxOne() (
pattern="$1"
file="$2"
IFS=$'\n'
set -f
results=( $(grep -m2 -- "$pattern" "$file") )
if [ "${#results[@]}" -eq 1 ]; then
printf -- '%s\n' "${results[@]}"
return 0
else
return 1
fi
)
将这些行添加到您的文件中~/.bashrc
,或者只是将它们粘贴到正在运行的 bash 会话的终端中,然后您可以执行以下操作:
maxOne foo file
foo
要在 中搜索file
。请注意,-m
此处使用的选项(最大结果)是为了提高grep
在两场比赛后退出的效率,并非所有版本都支持,grep
因此如果它给您一个错误,只需将其删除。这不是必需的,它只是加快速度。
重要的:这不适用于多行搜索字符串,grep -z
如果您grep
支持的话,您可以使用多行搜索字符串。如果您需要能够处理多行搜索模式,则需要不同的方法。此外,这不适用于匹配空行的模式(例如grep '^$' file
)。斯特凡的解决方案将处理空行,因此如果这是一个问题,这将是一个更好的选择。与我不同的是,他还可以处理多个文件,这是一个很好的福利。
答案2
你可以这样做:
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 "$@"
)
再unique_egrep pattern *.txt
比如。
这里使用-e 'code' -E /dev/null
(代替'code'
)技巧能够处理任意文件路径。
所有-e
、-E
、BEGINFILE
和ENDFILE
都是nextfile
GNU 扩展(尽管nextfile
现在也在许多其他实现中找到)。