检查所有模式是否都在文件中

检查所有模式是否都在文件中

假设我有一个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

具有grepPCRE扩展并且还使用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'

相关内容