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

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

假設我有一個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'

相關內容