假设我有一个patterns.txt
并且想要检查这些模式中的每一种是否都存在于某个文件中。
我可以做类似的事情:
for pattern in $(cat patterns.txt); do
if ! grep -q "$pattern" file.txt; then
echo "Error: missing pattern $pattern"
fi
done
echo "All patterns found"
但这是低效的,因为它必须重新扫描file.txt
每个模式(如果我们不是在文件中寻找来自可能很大的管道的流中的模式,那么事情就不那么简单了)。
有没有办法grep
(或其他工具)检查是否全部模式存在吗?
答案1
cat file.txt | awk '
NR == FNR {seen[$0] = 0; next}
{for (p in seen) if ($0 ~ p) seen[p]++}
END {
for (p in seen)
if (seen[p] == 0) {
missing++
print "missing pattern", p
}
if (missing == 0) print "all found"
exit missing
}
' patterns.txt -
将命令替换cat
为任何生成文本的管道。
答案2
这可能效果很好:
sort -u patterns.txt > sorted_patterns.txt # only once
diff -sq <(grep -o -f sorted_patterns.txt file.txt | sort -u) sorted_patterns.txt
如果您有固定字符串而不是模式,请使用-F
.这使得grep
速度快很多!
你可以也使用cmp
代替diff -s
。这可能会快一点,但无法显示缺少的内容。
如果未找到所有模式,则输出:
Files /dev/fd/63 and /dev/fd/62 differ
或者如果已找到所有模式:
Files /dev/fd/63 and /dev/fd/62 are identical
离开-q
才知道什么不见了。
2a3
> missing_word
答案3
具有grep
PCRE扩展并且还使用printf
命令的力量;你会做类似的事情:
<infile grep -qzP "(?s)$(printf "(?=.*?%s)" $(<pattern.txt))" &&
echo 'all matched' ||
echo 'one or more pattern(s) does not found'
如果所有模式(在任何订单) 在输入文件中找到内菲莱然后发短信all matched
将转到输出;否则文本one or more pattern(s) does not found
会回声。
这会将模式用作匹配模式,例如pat[01]
将匹配pat0
& pat1
;要匹配精确的模式,请从pat[01]
字面上更改printf
控制修饰符,以转义特殊字符。%s
%q
<infile grep -qzP "(?s)$(printf "(?=.*?%q)" $(<pattern.txt))" &&
echo 'all matched' ||
echo 'one or more pattern(s) does not found'