Подтвердить что ты не робот

Как найти два слова в одной строке?

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

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

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

Зачем?

4b9b3361

Ответ 1

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

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

grep "word1" FILE | grep "word2"

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

Если вам просто нужно подсчитать, сколько строк имеет 2 слова в одной строке, выполните следующие действия:

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

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

Ответ 2

Предписание

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

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, чтобы свести к минимуму количество данных, обрабатываемых вторым.

Диагностика

Первоначальный script:

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

Это нечетная последовательность команд. Первый grep будет подсчитывать количество вхождений слова "1" на его стандартный ввод и печатать это число на его стандартном выходе. Пока вы не укажете 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' "[email protected]"
grep 'word1.*word2' "[email protected]"

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

Ответ 3

вы можете использовать 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 медленнее.

Ответ 4

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

grep "word1" logs | grep "word2"

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

Ответ 5

Попробуйте кошку с помощью команды ниже

cat log|grep -e word1 -e word2

Ответ 6

grep word1 file_name | grep word2

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

Ответ 7

Использовать grep:

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

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

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

Ответ 8

git grep

Вот синтаксис с использованием git grep объединяющий несколько шаблонов с использованием логических выражений:

git grep -e pattern1 --and -e pattern2 --and -e pattern3

Приведенная выше команда напечатает строки, соответствующие всем шаблонам одновременно.

Если файлы не находятся под контролем версий, добавьте параметр --no-index.

Поиск файлов в текущем каталоге, который не управляется Git.

Проверьте man git-grep за помощью.

Смотрите также: