grep для 2 слов, существующих в одной строке


Как я могу grep для строк, которые содержат два входных слова в строке? Я ищу строки, которые содержат оба слова, как мне это сделать? Я попробовал трубу вот так:

 grep -c "word1" |grep -r "word2" logs

Он просто застревает после первой команды трубы. зачем?

8 85

8 ответов:

почему вы проходите -c? Это просто покажет количество матчей. Точно так же нет причин использовать -r. Я предлагаю вам прочитать man grep.

чтобы grep для 2 слов, существующих в одной строке, просто сделайте:

grep "word1" FILE | grep "word2"

grep "word1" FILE будет печатать все строки, которые имеют word1 в них из файла, а затем grep "word2" будет печатать строки, которые имеют word2 в них. Следовательно, если вы объедините их с помощью трубы, он покажет строки, содержащие как word1, так и слово2.

если вы просто хотите подсчитать, сколько строк было 2 слова в одной строке, сделайте:

grep "word1" FILE | grep -c "word2"

кроме того, чтобы ответить на ваш вопрос, почему он застрял: in grep -c "word1", вы не указали файл. Таким образом, grep ожидает ввода от stdin, вот почему он, кажется, висит. Вы можете нажать Ctrl+D чтобы отправить EOF (конец файла), чтобы он вышел.

предписание

один простой переписать команду в вопросе:

grep "word1" logs | grep "word2"

первый grep находит строки с 'word1' из файла 'logs' и затем передает их во второй grep который ищет строки, содержащие 'word2'.

однако не обязательно использовать две такие команды. Вы можете использовать расширенную grep (grep -E или egrep):

grep -E 'word1.*word2|word2.*word1' logs

если вы знаете ,что 'word1' будет предшествовать 'word2' на линия, вам даже не нужны альтернативы и регулярные grep будет делать:

grep 'word1.*word2' logs

варианты "одна команда" имеют то преимущество, что выполняется только один процесс, и поэтому строки, содержащие "word1", не должны передаваться через канал во второй процесс. Насколько это важно, зависит от того, насколько велик файл данных и сколько строк соответствует "word1". Если файл небольшой, производительность вряд ли будет проблемой, и запуск двух команд в порядке. Если файл большой, но только несколько строк содержат "word1", там не будет много данных, передаваемых по каналу, и использование двух команд прекрасно. Однако, если файл огромен и "word1" встречается часто, то вы можете передавать значительные данные по каналу, где одна команда избегает этих накладных расходов. Против этого регулярное выражение является более сложным; вам может потребоваться проверить его, чтобы узнать, что лучше, но только если производительность действительно имеет значение. Если вы выполняете две команды, вы должны стремиться выбрать менее часто встречающиеся слово, в первом grep для минимизации объема данных, обрабатываемых вторым.

Диагностика

исходный скрипт:

grep -c "word1" | grep -r "word2" logs

это странная последовательность команд. Первый grep собирается подсчитать количество вхождений "word1" на его стандартном входе и распечатать это число на его стандартном выходе. Пока вы не укажете EOF (например, набрав Control-D), он будет сидеть там, ожидая вас, чтобы ввести что-то. Второй grep выполняет рекурсивный поиск 'word2' в файлах под каталогом logs (или, если это файл, в файле logs). Или, в моем случае, это не удастся, так как нет ни файл, ни каталог logs где я запускаю трубопровод. Обратите внимание, что второй grep не читает стандартный ввод, так что труба лишняя.

С Bash родительская оболочка ждет, пока все процессы в конвейере не выйдут, поэтому она сидит в ожидании grep -c чтобы закончить, что он не будет делать, пока вы не укажете EOF. Следовательно, ваш код, кажется, застрял. С Heirloom Shell, второй grep завершает и завершает работу, и оболочка снова запрашивает. Теперь у вас есть два запущенных процесса, первый grep и оболочка, и они оба пытаются читать с клавиатуры, и не определено, какой из них получает любую заданную строку ввода (или любую заданную индикацию EOF).

обратите внимание, что даже если вы ввели данные в качестве входных данных первый grep, вы получите только те строки, которые содержат 'word2', показанные на выходе.


Примечание:

в свое время использовался ответ:

grep -E 'word1.*word2|word2.*word1' "$@"
grep 'word1.*word2' "$@"

это вызвало комментарии ниже.

вы можете использовать awk. вроде этого...

cat <yourFile> | awk '/word1/ && /word2/'

порядок не важен. Так что если у вас есть файл, и...

файл с именем file1 с содержит:

word1 is in this file as well as word2
word2 is in this file as well as word1
word4 is in this file as well as word1
word5 is in this file as well as word2

затем,

/tmp$ cat file1| awk '/word1/ && /word2/'

в результате

word1 is in this file as well as word2
word2 is in this file as well as word1

да, awk медленнее.

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

grep "word1" logs | grep "word2"

Если вы хотите подсчитать вхождения, то поставьте '-c' на второй grep.

вы попробуйте ниже команду

cat log|grep -e word1 -e word2

grep word1 file_name | grep word2

это кажется мне самым простым способом

команда grep:

grep -wE "string1|String2|...." file_name

или вы можете использовать:

echo string | grep -wE "string1|String2|...."

чтобы grep два слова одновременно, используйте эту команду оболочки:

eval "</dev/stdin $(printf "|grep '%s'" word1 word2)" FILE

Если вы используете это чаще, это можно определить как псевдоним:

alias grep-all="</dev/stdin $(printf "|grep '%s'" word1 word2)"

затем запустите просто:

grep-all FILE

Если в файле хранится несколько шаблонов, см.:сопоставьте все шаблоны из файла сразу.

кроме того, проверить: как запустить grep с несколькими и шаблонами?