awk + как перехватить адрес электронной почты между символами

Другой вариант заключается в том, чтобы уточнить, что именно вы ищете. Например:

whois stackoverflow.com | grep -E '^[[:space:]]*(Registr(ar|ant|y)|Sponsoring).*: '

Это извлекает только строки, которые начинаются с необязательного пробела перед 'Registrar', 'Registrant', 'Registry' или 'Sponsoring', за которым следует любое число (ноль или больше) любых символов, за которым следует двоеточие и пробел.

(BTW, здесь используется grep -E, а не устаревший и устаревший egrep. Они делают одно и то же.)

Output:

   Registrar: NAME.COM, INC.
   Sponsoring Registrar IANA ID: 625
Registry Domain ID: 108907621_DOMAIN_COM-VRSN 
Registrar WHOIS Server: whois.name.com 
Registrar URL: http://www.name.com 
Registrar Registration Expiration Date: 2016-12-26T19:18:07Z 
Registrar: Name.com, Inc. 
Registrar IANA ID: 625 
Registry Registrant ID:  
Registrant Name: Sysadmin Team 
Registrant Organization: Stack Exchange, Inc. 
Registrant Street: 110 William St , Floor 28 
Registrant City: New York 
Registrant State/Province: NY 
Registrant Postal Code: 10038 
Registrant Country: US 
Registrant Phone: +1.2122328280 
Registrant Email: sysadmin-team@stackoverflow.com 
Registry Admin ID:  
Registry Tech ID:  
Registrar Abuse Contact Email: abuse@name.com 
Registrar Abuse Contact Phone: +1.1 7203101849 

BTW, при тестировании любой формы обработки текста (включая регулярные выражения) на тексте из медленных источников (например, запрос к базе данных или из удаленного источника, такого как whois или http-сервер), полезно запустить команду slow один раз и перенаправить вывод в файл, а затем провести тест с этим файлом. Когда вы получите то, что хотите, убедитесь, что это работает так же, как и с прямыми (свежими) данными.

например

whois stackoverflow.com > so.txt

Другие полезные вещи, которые можно сделать с выводом whois:

  1. извлечение блока Domain в начале whos (строки поля начинаются с 4 пробелов и заканчиваются двоеточием):

    grep -Ei '^[[:blank:]]+.*:[[:blank:]]' so. txt

Выход:

   Domain Name: STACKOVERFLOW.COM
   Registrar: NAME.COM, INC.
   Sponsoring Registrar IANA ID: 625
   Whois Server: whois.name.com
   Referral URL: http://www.name.com
   Name Server: CF-DNS01.STACKOVERFLOW.COM
   Name Server: CF-DNS02.STACKOVERFLOW.COM
   Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
   Updated Date: 26-nov-2015
   Creation Date: 26-dec-2003
   Expiration Date: 26-dec-2016
  1. извлеките блок Registrant, начиная с поля `Domain Name' и заканчивая полем 'Registrar Abuse Contact Phone':

    sed -n -e '/^Domain Name:/,/^Registrar Abuse Contact Phone:/p' so.txt

  2. оба вышеуказанных варианта вместе:

    sed -n -e '/^Domain Name:/,/^Registrar Abuse Contact Phone:/p /^[[:blank:]]+.*:[[:blank:]] /p'

  3. Вывод всех вышеперечисленных данных может быть легко обработан с помощью awk или любого другого инструмента обработки текста, который можно заставить использовать символ двоеточия (:) в качестве разделителя полей.

3
24.03.2017, 14:51
4 ответа

Самый простой способ, который я могу придумать, это использование GNU grep:

$ grep -Po '<\K[^>]+(?=>)' file 
jdyefc@nsuwtcvc
ejd2ydt2@dv2dg2vgv
i2dmi32@hd2vdg 
2udhu2@cdrrc

Параметр -o означает "печатать только совпадающую часть строки", а -P активирует Perl-совместимые регулярные выражения. Это позволяет нам использовать \K, что означает "не считать частью совпадения все, что совпало до этого момента" и положительные lookaheads. Таким образом, регекс будет соответствовать <, затем любому отрезку не > символов, за которым следует >.

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

grep -Po '<\K[^>]+@[^>]+(?=>)' file 
10
27.01.2020, 21:07

Другой вариант:

perl -lne 'print $1 while /<(.*?)>/g'

Захват скобок в $ 1 , . *? делает совпадение не -жадно, т.е. останавливается, как только может.

С awk :

awk -F'<' '{ for(i = 2 ; i <= NF ; i++) { sub(/>.*/, "", $i); print $i; } } ' 

Разделить строку на <, игнорировать первую часть, вывести остальные после удаления всего, что начинается с > . Это напечатает оставшуюся часть строки, если нет > после <.

1
27.01.2020, 21:07

Использование gawk:

awk -v RS="[<>]" '/@/' 
4
27.01.2020, 21:07
perl -lne 'print for /<\K[^>]+/g'
4
27.01.2020, 21:07

Теги

Похожие вопросы