Проверьте, все ли шаблоны есть в файле

Проверьте, все ли шаблоны есть в файле

Допустим, у меня есть файл 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'

Связанный контент