awk + cómo capturar la dirección de correo electrónico entre los personajes

Tengo una list muy larga de correos electrónicos entre los < y > caracteres:

 smeimebv2t <jdyefc@nsuwtcvc>; jdedyvt <ejd2ydt2@dv2dg2vgv>; didi2jd2m <i2dmi32@hd2vdg >; 3idm23i2m <2udhu2@cdrrc> . . . 

¿Cómo puedo usar awk o perl one liner para capturar solo las direcciones de correo electrónico entre < > ?

ejemplo:

 more results.out jdyefc@nsuwtcvc ejd2ydt2@dv2dg2vgv i2dmi32@hd2vdg 2udhu2@cdrrc 

La forma más simple que puedo pensar es usando GNU grep :

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

El -o significa "solo imprimir la región de coincidencia de la línea" y el " -P activa las expresiones regulares compatibles de Perl. Éstos nos permiten usar \K que significa "no considerar nada emparejado hasta este punto como parte de la coincidencia" y lookaheads positivos . Por lo tanto, la expresión regular coincidirá con un < , luego cualquier extensión de caracteres no > seguida de un > .

Tenga en count que esto también coincidirá con <foo> que no es un correo electrónico. Para restringir a los correos electrónicos solamente (cadenas con un @ ), puede usar:

 grep -Po '<\K[^>]+@[^>]+(?=>)' file 
 perl -lne 'print for /<\K[^>]+/g' 

Usando gawk:

 awk -v RS="[<>]" '/@/' 

Otra variante:

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

La captura de paréntesis a $1 .*? hace que el partido no sea codicioso, es decir, se detenga tan pronto como sea posible.

Con awk :

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

Divida la línea en < 's, ignore la primera parte e imprima otras después de eliminar cualquier cosa que comience con > . Esto imprimirá el rest de la línea si no hay > después de un < .