Файлы Grep, содержащие два или более появления определенной строки

Мне нужно найти файлы, где определенная строка появляется дважды или более.

Например, для трех файлов:

Файл 1:

Hello World!

Файл 2:

Hello World!
Hello !

Файл 3:

Hello World!
Hello
Hello Again.

-

Я хочу grep Hello и получить файлы 2 и 3.

Ответы

Ответ 1

Как насчет этого:

grep -o -c Hello * | awk -F: '{if ($2 > 1){print $1}}'

Ответ 2

Поскольку вопрос помечен grep, вот решение, использующее только эту утилиту и bash (не требуется awk):

#!/bin/bash
for file in *
do
  if [ "$(grep -c "Hello" "${file}")" -gt 1 ]
  then
    echo "${file}"
  fi
done

Может быть однострочным:

for file in *; do if [ "$(grep -c "Hello" "${file}")" -gt 1 ]; then echo "${file}"; fi; done

Объяснение

  • Вы можете изменить оператор for file in * с помощью любого расширения оболочки, которое вы хотите получить для всех файлов данных.
  • grep -c возвращает количество строк, соответствующих шаблону, с несколькими совпадениями в строке, все еще считающейся только для одной строки.
  • if [ ... -gt 1 ] проверьте, что в файле сопоставляется более одной строки. Если да:
  • echo ${file} напечатать имя файла.

Ответ 3

Вам понадобится grep, который может распознавать шаблоны в конце строки ( "привет", за которым следует что-либо (возможно, даже окончание строки), а затем "привет" )

Поскольку grep обрабатывает ваши файлы по строкам, он (сам по себе) не является правильным инструментом для задания - если только вам не удастся втиснуть весь файл в одну строку.

Теперь это легко, например, с помощью команды tr, заменяя окончания строки пробелами:

if cat $file | tr '\n' ' ' | grep -q 'hello.*hello'
then
   echo "$file matches"
fi

Это довольно эффективно даже в больших файлах со многими (скажем, 100000) линиями и может быть еще более эффективным, вызывая grep с помощью --max-count=1, что позволяет остановить поиск после того, как совпадение найдено. Не имеет значения, находятся ли два hellos в одной строке или нет.

Ответ 4

Этот awk будет печатать имя файла всех файлов с 2 или более Hello

awk 'FNR==1 {if (a>1) print f;a=0} /Hello/ {a++} {f=FILENAME} END {if (a>1) print f}' *
file2
file3

Ответ 5

После прочтения вашего вопроса, я думаю, вы также захотите найти случай hello hello в одной строке. (find files where a specific string appears twice or more.), поэтому я придумываю этот однострочный слой:

awk -v p="hello" 'FNR==1{x=0}{x+=gsub(p,p);if(x>1){print FILENAME;nextfile}}' *
  • в приведенной выше строке p - это шаблон, который вы хотите искать
  • он выведет имя файла, если файл содержит шаблон два или более раз. независимо от того, находятся они в одной или разных линиях.
  • во время обработки, после проверки некоторой строки, если мы уже нашли два или более шаблона, напечатаем имя файла и прекратим обработку текущего файла, возьмите следующий входной файл, если он еще есть. Это полезно, если у вас большие файлы.

Небольшой тест:

kent$  head f*
==> f <==
hello hello world

==> f2 <==
hello

==> f3 <==
hello
hello
SK-Arch 22:27:00 /tmp/test
kent$ awk -v p="hello" 'FNR==1{x=0}{x+=gsub(p,p);if(x>1){print FILENAME;nextfile}}' f*
f
f3

Ответ 6

grep -c Привет * | egrep -v ': [01] $' | sed 's/: [0-9] * $//'

Ответ 7

Другой способ:

grep Hello * | cut -d: -f1 | uniq -d

Grep для строк, содержащих "Hello"; сохраняйте только имена файлов; напечатайте только дубликаты.

Ответ 8

Передача на язык сценариев может быть излишней, но зачастую это намного проще, чем просто использовать awk

grep -rnc "Hello" . | ruby -ne 'file, count = $_.split(":"); puts "#{file}: #{count}" if count&.to_i >= 2'

Так что за ваш вклад мы получаем

$ grep -rnc "Hello" . | ruby -ne 'file, count = $_.split(":"); puts "#{file}: #{count}" if count&.to_i >= 2'

./2: 2
./3: 3

Или опустить счет

grep -rnc "Hello" . | ruby -ne 'file, _ = $_.split(":"); puts file if count&.to_i >= 2'