Как сделать так, чтобы grep совпадал только в том случае, если совпадает вся строка?


104

У меня есть такие:

$ cat a.tmp
ABB.log
ABB.log.122
ABB.log.123

Я хотел найти точное совпадение с ABB.log.

Но когда я сделал

$ grep -w ABB.log a.tmp
ABB.log
ABB.log.122
ABB.log.123

он показывает их все.

Могу ли я получить то, что хотел, с помощью grep?

Ответы:


105

Просто укажите якоря регулярного выражения.

grep '^ABB\.log$' a.tmp

2
Необходимы оба якоря (^ и $).
user562374

2
Хороший! А если я использую регулярное выражение для сопоставления из файла? "grep -f patterns a.tmp" ??
green69

@ green69 С опозданием на несколько лет, но вы можете использовать sed для добавления якорей перед передачей шаблонов в grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Randoms

156
grep -Fx ABB.log a.tmp

На странице руководства grep:

-F, --fixed-strings
Интерпретировать ШАБЛОН как (список) фиксированных строк
-x, --line-regexp
Выбирать только те совпадения, которые точно соответствуют всей строке.


2
к сожалению, не удалось использовать -F.
Johnyy

@Johnyy Нет -F? ты на солярисе? Если да, то используйте/usr/xpg4/bin/grep
Scrutinizer

9
Я использую grepвнутри сценария bash, и этот вариант лучше, чем использование регулярного выражения, как предлагается в принятом ответе. Потому что у меня есть специальный символ внутри переменной, которую я ищу (например, .), и мне не нужно избегать их при использовании команды.
Густаво Штраубе

1
лучший ответ IMO, потому что он позволяет использовать специальные символы без экранирования
ReneGAED

1
Это лучше, потому что он также работает с переменными.
ybenjira 02

23

Вот что я делаю, хотя якоря - лучший способ:

grep -w "ABB.log " a.tmp

Как этот .. он вернет совпадение в первой строке
user765443

1
Для этого требуется пробел после ABB.log, что не является общим случаем, т. Е. В большинстве случаев он не работает.
Jahid

3

Большинство предложений не будут выполнены, если будет хотя бы один начальный или конечный пробел, что будет иметь значение, если файл редактируется вручную. Это сделает его менее уязвимым в этом случае:

grep '^[[:blank:]]*ABB\.log[[:blank:]]*$' a.tmp

Простой цикл while-read в оболочке сделает это неявно:

while read file
do 
  case $file in
    (ABB.log) printf "%s\n" "$file"
  esac
done < a.tmp


1

Я намерен добавить некоторые дополнительные пояснения относительно попыток OP и других ответов.

Вы также можете использовать решение Джона Кугельмана следующим образом:

grep -x "ABB\.log" a.tmp

заключение строки в кавычки и экранирование точки ( .) делает -Fфлаг больше не нужен .

Вам нужно экранировать .(точку) (потому что он соответствует любому символу (не только .), если он не экранирован) или использовать -Fфлаг с grep. -Fflag делает его фиксированной строкой (не регулярным выражением).

Если вы не заключаете строку в кавычки, вам может потребоваться двойная обратная косая черта, чтобы избежать точки ( .):

grep -x ABB\\.log a.tmp


Тест:

$ echo "ABBElog"|grep -x  ABB.log
ABBElog #matched !!!
$ echo "ABBElog"|grep -x  "ABB\.log"
#returns empty string, no match


Примечание:

  1. -x заставляет соответствовать всей строке.
  2. Ответы с использованием неэкранированного .без -Fфлага неверны.
  3. Вы можете избежать -xswitch, заключив строку шаблона в символы ^и $. В этом случае убедитесь, что вы не используете -F, а избегаете ., потому что -Fэто предотвратит интерпретацию регулярного выражения ^и $.


РЕДАКТИРОВАТЬ: (Добавление дополнительных пояснений в отношении @hakre):

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

Пример:

echo -f |grep -- "-f"     # where grep "-f" will show error
echo -f |grep -F -- "-f"  # whre grep -F "-f" will show error
grep "pat" -- "-file"     # grep "pat" "-file" won't work. -file is the filename

Вы действительно заметили, что -F отсутствовал в вашем случае? Если да, то не могли бы вы сказать, в каком именно случае это было?
hakre

@hakre Вы полностью прочитали мой ответ? Я объяснил (довольно четко), почему -Fон не понадобится, если .экранирован правильно.
Джахид

Конечно. Конечно, я просто спрашиваю: был ли -Fдоступен, когда вы это писали? Если нет, то какую систему вы использовали? Я пока не смог найти эту информацию в вашем ответе, и даже сейчас, когда я перечитываю ее снова. Так что действительно уверен, я прочитал ваш ответ полностью как минимум дважды. ;)
hakre

@hakre Конечно -Fбыл доступен. (Я сказал: «или используйте -Fфлаг с grep»)
Джахид

Спасибо за понимание. Остается только один маленький вопрос: если -Fэто ответ, зачем беспокоиться о побеге? Каково ваше мнение об этом?
hakre


-1
    $ cat venky
    ABB.log
    ABB.log.122
    ABB.log.123

    $ cat venky | grep "ABB.log" | grep -v "ABB.log\."
    ABB.log
    $

    $ cat venky | grep "ABB.log.122" | grep -v "ABB.log.122\."
    ABB.log.122
    $

1
Это также будет соответствовать файлам, которые заканчиваются на ABB.log, и точки должны быть экранированы.
Scrutinizer

-1

У меня работает :

grep "\bsearch_word\b" text_file > output.txt  

\b указывает / устанавливает границы.

Кажется, работает довольно быстро


Это также соответствует любой строке, содержащей search_wordразделенные границами слова. Например, это будет соответствовать строке «foo search_word bar».
Рохан Сингх

-2

Это с HPUX, если в содержимом файлов есть пробелы между словами, используйте это:

egrep "[[:space:]]ABC\.log[[:space:]]" a.tmp


OP хотел сопоставить всю строку, а не слово, разделенное пробелами внутри строки.
Кейт Томпсон,


-3

Мне нужна была эта функция, но я также хотел убедиться, что не возвращаю строки с префиксом перед ABB.log:

  • ABB.log
  • ABB.log.122
  • ABB.log.123
  • 123ABB.log

grep "\WABB.log$" -w a.tmp

Это будет соответствовать только в том случае, если будет выполнено ведущее значение \W, то есть любой непробельный символ, поэтому xABBxlog.
bschlueter
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.