Unix Script для поиска текстовых файлов, которые должны содержать два конкретных ключевых слова - PullRequest
2 голосов
/ 24 февраля 2012

РЕШЕНИЕ НАЙДЕНО: (спасибо Жолту Ботыкай и Майку Райану)

Точный перевод приведенного ниже сценария на awk однострочник:

find /home/data/ -type f -exec awk '/PATTERN1/ {c++} /PATTERN2/ {d++} c>0 && d>0 {print ARGV[1] ; exit 0 } END { if (! c || ! d) {exit 1}}' \{\} \; > assetsToDelete.txt 2>&1

см. https://stackoverflow.com/a/9442764/356815

ОРИГИНАЛЬНЫЙ ВОПРОС:

Вопрос очень прост, но я не нашел возможности создать быстрый сценарий для этого.

У меня есть 100 000 текстовых файлов, и мне нужно найти все те, которые удовлетворяют двум условиям.

Мой сценарий выглядит так, но он медленный, как ад ... лучше?

echo Searching for first criteria...
date
grep -rl 'PATTERN1' /home/data/assets/ > assets.txt
file=assets.txt

echo Now filtering for second criteria
date
for i in `cat $file`
do
  grep -l 'PATTERN2' $i >> assetsToDelete.txt
done
echo DONE
date

Так что я ищу возможность сделать что-то вроде этого:

Поиск в каталоге и отфильтровывание всех файлов, которые выполняют условие1 И условие2, за один шаг. Условия, как правило, соответствуют шаблонам, но в разных строках содержимого файла.

Ответы [ 3 ]

7 голосов
/ 24 февраля 2012

Хорошо с awk вы можете сделать что-то вроде:

awk '/FIRSTPATTERN/ {c++}
     /SECONDPATTERN/ {d++}
     c>0 && d>0 {print ARGV[1] ; exit 0 } 
     END { if (! c || ! d) {exit 1}}' INPUTFILE

Теперь вы можете использовать это как:

find /YOUR/PATH -type f -exec \
awk '/FIRSTPATTERN/ {c++}
     /SECONDPATTERN/ {d++}
     c>0 && d>0 {print ARGV[1] ; exit 0 } 
     END { if (! c || ! d) {exit 1}}' \{\} \;
1 голос
/ 24 февраля 2012

Вы можете сделать это ...

grep -rl '<ref-date>1960' | xargs grep -l '<source>true</source>'

... но это не будет невероятно быстрым или чем-то еще, потому что вы все равно сканируете файлы дважды.

0 голосов
/ 25 февраля 2012

Exakt one-liner с awk, выполняющим те же действия, что и скрипт в вопросе, выглядит следующим образом:

find /home/data/ -type f -exec awk '/PATTERN1/ {c++} /PATTERN2/ {d++} c>0 && d>0 {print ARGV[1] ; exit 0 } END { if (! c || ! d) {exit 1}}' \{\} \; > assetsToDelete.txt 2>&1

Спасибо всем за помощь в поиске этого!

c=0 и d=0 важны, чтобы awk не печатал одно и то же имя файла несколько раз в выходной файл assetsToDelete.txt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...