У меня есть файл с содержимым, похожим на:
google.com,9,AB+CD,nonAB+nonCD
youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD
Количество столбцов не фиксировано. Но первый столбец — это URL, второй — число, начиная с третьего — ключевые слова, разделенные запятыми, но они различаются от сайта к сайту.
Я хочу подсчитать количество URL-адресов (строк), где я могу контролировать, какие ключевые слова находятся в строке. Например,
1) AB+CD
без nonAB
и nonCD
. Примечание: слово AB+CD может встречаться много раз. 2) AB+CD без вхождения nonCD
(но это нормально, если есть что-то еще)
Как искать строку в строке И гарантировать отсутствие другой строки. Когда я использую:
grep 'AB+CD' test.txt > result.txt
Он выводит каждую строку, где встречается «AB+CD».
Что делать, если я хочу напечатать строку, в которой есть только «AB+CD», чтобы получить:
youtube.com,9,AB+CD,AB+CD
Или есть «AB+CD» с чем угодно, кроме «nonAB», чтобы получить:
youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD
решение1
Если вам нужен просто текстовый поиск, не заботясь о столбцах, вы можете связать инвертированное соответствие grep -v
следующим образом:
cat input.txt | grep 'IncludedText' | grep -v 'ExcludedText'
Если вы хотите выполнить правильную фильтрацию по столбцу, вам нужно будет использовать что-то вроде awk
.
решение2
Общие приемы:
Строки, содержащие
foo
плюс строки, содержащиеbar
(foo OR bar
):grep -e foo -e bar
Строки, содержащие
foo
иbar
в одной строке (foo AND bar
):grep foo | grep bar
Строки, не содержащие
baz
(NOT baz
):grep -v baz
С помощью этих кирпичиков вы можете построить свою логику. Проблема -v
не ограничивается одним шаблоном, она глобальна для всего grep
(по крайней мере, в моем Debian). Это делает NOT (foo OR bar)
возможным:
grep -v -e foo -e bar
что эквивалентно (NOT foo) AND (NOT bar)
:
grep -v foo | grep -v bar
Однако NOT (foo AND bar)
(логически эквивалентно (NOT foo) OR (NOT bar)
) не так просто. Мы можем попытаться получить foo AND bar
с помощьюодинокий(расширенный) grep
:
Снова строки, содержащие
foo
иbar
в одной строке (foo AND bar
):grep -E 'foo.*bar|bar.*foo'
Теперь, чтобы получить NOT (foo AND bar)
:
grep -v -E 'foo.*bar|bar.*foo'
Я не уверен, что вышеизложенное является полной системой при работе с более чем двумя шаблонами. Тем не менее, некоторые из ваших проблем можно решить с его помощью. Пример:
AB+CD
безnonAB
иnonCD
Если я правильно понял, то этоAB+CD AND NOT (nonAB OR nonCD)
grep AB+CD | grep -v -e nonAB -e nonCD
Обратите внимание, что этот запрос все усложняет:
Я хочу напечатать строку, где есть только «AB+CD»
Можно сказать, grep ,AB+CD,AB+CD
что так и будет, но поскольку «количество столбцов не фиксировано», я думаю, вы захотите разделить эти две строки:
youtube.com,9,AB+CD,AB+CD,AB+CD
youtube.com,9,AB+CD,AB+CD,banana
В таких случаях вам понадобятся более сложные регулярные выражения или другие инструменты (например awk
, ).
решение3
Пока вы получите ответ здесь, вам стоит взглянуть начеловек grep(может быть подавляющим) иНекоторые примеры. На данный момент вот ответ:
С использованиемgrep
grep "foobar" test.txt
будет искать строки, содержащие слово foobar
в файле test.txt
, и отображать все вхождения, тогда как ,
grep "foo" -v "bar" test.txt
будет искать строки, содержащие слово foo
, но не bar
. Мы получаем это из-за-v
переключатель, для которого страница руководства объясняет:
-v, --invert-match
Invert the sense of matching, to select non-matching lines.
(-v is specified by POSIX .)
Это просто означает, что он будет искать строки, содержащие эти слова (здесь bar
), но исключит их из окончательного отображения. Таким образоминвертирование поиска.
Также, чтобы подсчитать количество строк, соответствующих поиску, используйте-c
выключатель :
-c, --count
Suppress normal output; instead print a count of matching lines
for each input file. With the -v, --invert-match option (see below),
count non-matching lines. (-c is specified by POSIX .)
В качестве самостоятельного упражнения попробуйте выполнить поиск grep в файле.фубар.
Ответ
Поиск AB+CD
игнорирования nonAB
и nonCD
подсчета URL-адресов:
grep "AB+CD" test | grep -cve "non"
где -v "non"
просто проигнорирует оба nonAB
и nonCD
так как они оба имеют non
в них. И -c
даст общее количество совпадений вместо их вывода. Чтобы вывести совпадающие строки, просто проигнорируйте -c
.
Вы можете использовать его для отдельных инвертов:
grep "AB+CD" test | grep -cve "nonAB\|nonCD"
где \|
представляет OR
и означает либо nonAB
илиnonCD
точныйслово, указанное-e
выключатель.
Посоветовал бы вамсм. ответ Камиля, читайте man-страницы (вы знаете команду) как можно больше, старайтесь изо всех сил, когда ищете информацию в Интернете и служите сообществу. Не стесняйтесь добавлять больше подробностей для ответа.