grep для 2 слов, существующих в одной строке
Как я могу grep для строк, которые содержат два входных слова в строке? Я ищу строки, которые содержат оба слова, как мне это сделать? Я попробовал трубу вот так:
grep -c "word1" |grep -r "word2" logs
Он просто застревает после первой команды трубы. зачем?
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.
команда 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 с несколькими и шаблонами?