Как использовать grep с регулярным выражением и шаблонами из файла вместе? - PullRequest
0 голосов
/ 28 сентября 2018

Предположим, что файл содержит много шаблонов

.com
.re
.net
...

И есть файл, содержащий много данных

www.recent
www.remix3d.com
www.verisign.net

Что я хочу, так это то, что

www.remix3d.com
www.verisign.net

Я использую команду grep -f pattern_file data_file, но результат такой:

www.recent
www.remix3d.com
www.verisign.net

Поскольку .re соответствует www'.re'cent

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

Ответы [ 5 ]

0 голосов
/ 28 сентября 2018

Вы можете использовать grep -f с sed в процессе подстановки, который преобразует каждое расширение в pattern_file в правильное регулярное выражение:

grep -f <(sed 's/.*/\\&$/' pattern_file) data_file

www.remix3d.com
www.verisign.net

Выводsed команда:

sed 's/.*/\\&$/' pattern_file

\.com$
\.re$
\.net$
0 голосов
/ 28 сентября 2018

Похоже, ваши критерии на самом деле:

  • Файл шаблона - это на самом деле список STRINGS, а не список регулярных выражений (в котором точка (.) соответствует любому отдельному символу),
  • Шаблоны предназначены для сопоставления только в конце строк (так что в конце каждой строки в файле шаблона есть неявное значение $).

Чтобы соответствовать первому критерию, вы можете использовать опцию grep -F:

$ grep -F -f pattern_file data_file

Но это не помогает с .re, который встроен в середине одной из строк.Если вы можете изменить файл шаблона, изменив строки так:

\.com$
\.re$
\.net$

превратит их в нужные вам регулярные выражения.В противном случае вам, возможно, придется использовать что-то для PARSE этого файла шаблона, чтобы создать искомое регулярное выражение.Например, используя массив bash и некоторое расширение параметров:

$ mapfile -t a < pattern_file
$ declare -p a
declare -a a=([0]=".com" [1]=".re" [2]=".net")
$ printf -v new_re '|%s' "${a[@]}"
$ new_re="${new_re//./\\.}"         # escape dots within regex
$ new_re="(${new_re:1})\$"          # strip leading or-bar
$ echo "$new_re"
(\.com|\.re|\.net)$
$ grep -E "$new_re" data_file
www.remix3d.com
www.verisign.net

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

$ grep -f <(sed 's/\./\\./g;s/$/$/' pat) file
www.remix3d.com
www.verisign.net
0 голосов
/ 28 сентября 2018

Если вы не хотите изменять файл шаблона, то вы должны выполнить экранирование извне.Проверьте это.

> cat pattern
.com
.re
.net
> cat pattern_data
www.recent
www.remix3d.com
www.verisign.net
> grep $(sed 's/$/$/g;s/^/\\/g' pattern | tr '\n' '|' | sed 's/.$//g;s/|/\\|/g') pattern_data
www.remix3d.com
www.verisign.net
>
0 голосов
/ 28 сентября 2018

Обратите внимание, что существуют уже существующие инструменты для такого типа сопоставления доменных имен, для обработки открытого списка суффиксов .Для его обработки доступно множество библиотек , и некоторые из них сильно оптимизированы и будут намного быстрее, чем обработка списка регулярных выражений, если список суффиксов велик.

0 голосов
/ 28 сентября 2018

Файл шаблона должен содержать шаблоны (т.е. с правильно экранированными специальными символами), я предлагаю изменить файл шаблона следующим образом:

\.com$
\.ru$
\.net$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...