Як зробити так, щоб греп відповідав лише у тому випадку, якщо вся лінія збігається?


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
Обидва якоря (^ і $) потрібні.
користувач562374

2
Хороший! І якщо я використовую регулярний вираз для відповідності з файлу? "grep -f шаблони a.tmp" ??
green69

@ green69 Пізніше на кілька років, але ви можете використовувати sed, щоб додати якорі перед тим, як передавати шаблони в sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
греп

155
grep -Fx ABB.log a.tmp

Зі сторінки grep man:

-F, --fixed-string
Інтерпретувати PATTERN як (список) фіксованих рядків
-x, --line-regexp
Виберіть лише ті відповідники, які точно відповідають цілому рядку.


2
не вдалося використати -F на жаль.
Джонний

@Johnyy Ні -F? ти на Солярісі? Якщо так, використовуйте/usr/xpg4/bin/grep
Scrutinizer

9
Я використовую grepсценарій bash, і цей варіант краще, ніж використовувати регулярний вираз, як запропоновано у прийнятій відповіді. Оскільки в змінній, яку я шукаю (люблю .), я маю спеціальний символ, і мені не потрібно уникати їх під час використання команди.
Gustavo Straube

1
найкраща відповідь на ІМО, оскільки вона дозволяє спеціальним символам без втечі
ReneGAED

1
Це краще, оскільки воно також працює зі змінними.
ybenjira

23

Ось що я роблю, хоча найкраще використовувати якоря:

grep -w "ABB.log " a.tmp

Як цей .. він поверне матч Першої лінії
користувач765443

1
Для цього потрібен пробіл після ABB.log, що не є загальним випадком, тобто він вийде з ладу більшу частину часу.
Джахід

3

Більшість пропозицій не вдасться, якщо є стільки єдиного провідного чи кінцевого простору, що має значення, якщо файл редагується вручну. Це зробило б це менш сприйнятливим у такому випадку:

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

Простий цикл під час читання в оболонці зробить це неявно:

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


1

Я маю намір додати додаткові пояснення щодо спроб ОП та інших відповідей.

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

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

Цитування рядка та уникнення крапки ( .) змушує його більше не потребувати -Fпрапор.

Вам потрібно вийти з .(крапки) (тому що він відповідає будь-якому символу (не тільки .), якщо не вийшов) або використати -Fпрапор із грепом. -Fпрапор робить його фіксованою рядком (а не регулярним виразом).

Якщо ви не цитуєте рядок, вам може знадобитися подвійний нахил, щоб уникнути точки ( .):

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. Ви можете уникнути -xперемикання, обернувши рядок шаблону за допомогою ^та і $. У цьому випадку переконайтеся, що ви не використовуєте -F, а замість цього уникайте ., тому що -Fбуде перешкоджати трактуванню регулярних виразів ^і $.


EDIT: (Додавання додаткових пояснень щодо @hakre):

Якщо ви хочете зіставити рядок, починаючи з -, тоді вам слід використовувати --греп. Все, що далі, --буде сприйматися як вхід (не варіант).

Приклад:

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 Ви повністю прочитали мою відповідь? Я пояснив (досить чітко), чому -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, і крапки слід уникати.
Scruutinizer

-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


ОП хотіла збігатися з цілим рядком, а не з обмеженим пробілом словом у межах рядка.
Кіт Томпсон


-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.