AWK: accede al grupo capturado desde el patrón de línea

Si tengo un comando awk

pattern { ... } 

y el patrón usa un grupo de captura, ¿cómo puedo acceder a la cadena así capturada en el bloque?

Eso fue un paseo por el carril de la memoria …

Reemplacé awk por Perl hace mucho tiempo.

Aparentemente, el motor de expresiones regulares AWK no captura sus grupos.

podrías considerar usar algo como:

 perl -n -e'/test(\d+)/ && print $1' 

la bandera -n hace que perl bucle sobre cada línea como lo hace awk.

Con gawk, puede usar la función de match para capturar grupos entre paréntesis.

 gawk 'match($0, pattern, ary) {print ary[1]}' 

ejemplo:

 echo "abcdef" | gawk 'match($0, /b(.*)e/, a) {print a[1]}' 

salidas cd .

Tenga en cuenta el uso específico de gawk que implementa la función en cuestión.

Para una alternativa portátil, puede lograr resultados similares con match() y substr .

ejemplo:

 echo "abcdef" | awk 'match($0, /b[^e]*/) {print substr($0, RSTART+1, RLENGTH-1)}' 

salidas cd .

Esto es algo que necesito todo el tiempo, así que creé una función bash para ello. Está basado en la respuesta de Glenn Jackman.

Definición

Agregue esto a su .bash_profile, etc.

 function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; } 

Uso

Capture expresiones regulares para cada línea en el archivo

 $ cat filename | regex '.*' 

Capture el primer grupo de captura de expresiones regex para cada línea en el archivo

 $ cat filename | regex '(.*)' 1 

Puedes usar GNU awk:

 $ cat hta RewriteCond %{HTTP_HOST} !^www\.mysite\.net$ RewriteRule (.*) http://www.mysite.net/$1 [R=301,L] $ gawk 'match($0, /.*(http.*?)\$/, m) { print m[1]; }' < hta http://www.mysite.net/ 

Puede simular la captura en awak vanilla también, sin extensiones. Aunque no es intuitivo:

paso 1. usa gensub para rodear las coincidencias con algún personaje que no aparezca en tu cadena. paso 2. Usa dividir contra el personaje. paso 3. Todos los demás elementos de la matriz dividida son su grupo de captura.

 $ echo 'ab cb ad' |  awk '{split (gensub (/ a ./, SUBSEP "y" SUBSEP, "g", $ 0), cap, SUBSEP);  tapa de impresión [2] "|"  tapa [4];  } '
 ab | ad

Luché un poco al crear una función bash que envuelve la respuesta de Peter Tillemans, pero esto es lo que se me ocurrió:

función regex {perl -n -e “/ $ 1 / && printf \”% s \ n \ “,” ‘$ 1’}

Encontré que esto funcionó mejor que la función bash basada en awk de opsb para el siguiente argumento de expresión regular, porque no quiero que se imprima el “ms”.

 '([0-9]*)ms$'