2016-01-28 2 views
2

Я пишу сценарий оболочки для поиска файлов, содержащих строку «match1» И не содержит «match2».Найти файлы, которые содержат строку match1, но не содержит match2

я могу сделать это в 2-х частей:

  1. Grep -lr "match1" *>/TMP/match1
  2. Grep -lr "match2" *>/TMP/match2
  3. комм - 12/tmp/match1/tmp/match2

Есть ли способ, которым я могу достичь этого напрямую, не прорабатывая процесс создания временных файлов?

ответ

2

Я бы использовал поиск вместе с awk. awk могут проверить оба матча в одном счете, это означает, что вам не нужно обрабатывать все файлы дважды:

find -maxdepth 1 -type f -exec awk '/match1/{m1=1}/match2/{m2=1} END {if(m1 && !m2){print FILENAME}}' {} \; 

лучше объяснено в многострочный версии:

# Set flag if match1 occurs 
/match1/{m1=1} 

# Set flag if match2 occurs 
/match2/{m2=1} 

# After all lines of the file have been processed print the 
# filename if match1 has been found and match2 has not been found. 
END {if(m1 && !m2){print FILENAME}} 
+0

Вы должны были бы сбросить переменные и распечатать предыдущая FILENAME в 'FNR == 1' блоки для того, чтобы работать на более 1 файл. Использование ENDFILE с GNU awk вместо END может упростить работу. –

+0

Хорошая точка. Я признаю, что я тестировал только один файл. – hek2mgl

+0

Не так много времени, чтобы изменить ответ atm. Использовал help 'find', в то время как awk мог даже сделать это самостоятельно, используя метод FNR == 1, который вы упомянули. – hek2mgl

1

Есть ли способ, которым я может достичь этого напрямую, не проходя процесс создания временных файлов?

Да. Вы можете использовать трубопроводы и xargs:

grep -lr "match1" * | xargs grep -Lr "match2" 

Первый grep печатает имена файлов, содержащих спички в свой стандартный вывод, как вы знаете. Команда xargs считывает эти имена файлов со своего стандартного ввода и преобразует их в аргументы во вторую команду grep, добавляя их после уже предоставленных.

0

Вы можете сначала искать файлы, содержащие match1, а затем с помощью xargs передать его другому Grep с помощью -L или --files-without-match вариант.

grep -lr "match1" *|xargs grep -L "match2" 
2

Использование GNU AWK для мульти-гольцов RS:

awk -v RS='^$' '/match1/ && !/match2/ {print FILENAME}' * 
Смежные вопросы