Найдите точную строку с помощью grep

9

Например, у меня большой текстовый файл со многими адресами электронной почты, используя bash, мне нужно найти / проверить, существует ли электронная почта (или ее нет). Следует ли использовать (только) «якоря»?

grep '^user1@example.com' text_file

или есть лучшие способы? Мне нужно создать скрипт bash, и я бы хотел быть в безопасности.

Пол Халлен
источник
1
Является ли электронная почта единственным словом в строке?
Гленн Джекман
действительно: файл имеет следующий формат: user1@example.com example.com/user1
Пол Халлен,
1
В этом случае я бы использовал grep -q '^user1@example\.com\>'- с привязкой строки в начале и привязкой конца слова в конце.
Гленн Джекман
stackoverflow.com/questions/4709912/how-to-grep-the-exact-match
Сиро Сантилли 冠状 病毒 审查 六四 事件 法轮功

Ответы:

24

См. -F(Фиксированная строка в отличие от регулярного выражения) и -x(точный: соответствовать всей строке) параметры.

grep -Fx user1@example.com text_file

будет эквивалентно:

grep '^user1@example\.com$' text_file

(помните, что .это оператор регулярного выражения, соответствующий любому символу).

Используйте эту -qопцию, если вы хотите проверить, есть ли такая строка:

grep -Fxq user1@example.com text_file &&
  echo yes, that address is in that file.

Если строка для поиска и имя файла являются переменными:

grep -Fxqe "$email" < "$file"

Или

grep -Fxq -- "$email" < "$file"

Вы не хотите:

grep -Fxq "$email" "$file"

так как это может вызвать проблемы, если $emailили $fileначалось с -.

Если файл отсортирован (предпочтительно в вашей текущей локали C), вы можете ускорить процесс, используя commвместо grep:

printf '%s\n' user1@example.com | comm -12 - text_file

Преимущество станет более очевидным, когда вам нужно проверить несколько адресов электронной почты (например, в другом отсортированном файле):

comm -12 text_file emails_to_check

будет быстрее чем:

grep -Fxf emails_to_check text_file
Стефан Шазелас
источник
AFAIK, grep -Fxq -- "$email" "$file"тоже работает.
vinc17
Стефан, почему вы переключились с файлового ввода (обработанного grep) на стандартный ввод с помощью <перенаправителя? есть ли преимущества?
umläute
@ umläute и vinc17. Как я уже сказал, это покрывает имена файлов, начинающиеся с -. даже grep -- "$email" "$file"было бы проблемой для файла с именем -(который grepтрактуется как «стандартный ввод» )
Стефан Шазелас
6

Чтобы быть максимально эффективным, вы хотите остановиться после того, как будет найдено первое совпадение. Если у вас есть GNU grep, вы можете сделать это:

grep -m 1 '^user1@example\.com$' your_file

Если вы этого не сделаете, вы можете использовать Perl:

perl -nlE 'say and last if $_ eq q{user1@example.com}' your_file
Джозеф Р.
источник
4
-mявляется специфическим для GNU. Используйте POSIX, -qесли вы хотите эффективно проверить, есть ли такая линия.
Стефан Шазелас
3

Там много проверок по электронной почте. Одним из них является:

grep -E -o "\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b" text_file

Чтобы уточнить мой ответ.

Вы используете ^якорь, который указывает начало строки. Это не будет совпадать, если адрес электронной почты находится где-то между длинной строкой.

Валентин Байрами
источник
2
Спасибо. Это общие параметры grep для «извлечения» всех адресов электронной почты из файла. Мне нужно искать один за другим адрес электронной почты, используя чтение EMAIL, а затем с помощью grep, чтобы проверить его.
Пол Халлен
2

Ваша grepкоманда будет соответствовать всему, с чего начинается ^user1@example.com, включая сам адрес электронной почты, но также user1@example.com.spammer.com. так .как это специальный символ в регулярных выражениях, который соответствует любой клавише, вы должны экранировать его как\.

предполагая, что ваш текстовый файл содержит один адрес на строку, используйте:

EMAIL=user1@example\\.com
egrep "^${EMAIL}$" text_file

трейлинг $убедится, что строка заканчивается после адреса электронной почты. я также использую двойные кавычки ", так как они позволяют использовать переменные (в отличие от одинарных кавычек ')

umläute
источник
1
Это также соответствует user1@example-com.
Стефан Шазелас
@ StéphaneChazelas ты, конечно, прав; обновил ответ.
umläute
@ umläute Вы должны удвоить обратную косую черту. Но лучше использовать -Fx.
vinc17
@ vinc17, доу; убегая; во всяком случае, да, я согласен, что лучше использовать, -Fxно это ответ
Стефана
0

Учитывая общее литеральное / точное совпадение строк:

grep -w "search_word" <file>  >  output.txt

#\b shows boundaries over here.

или,

 grep  "\bsearch_word\b"  <file>  >  output.txt 
123User
источник