2009-07-12 13 views
8

¿Cómo realizo la acción en todos los grupos coincidentes cuando el patrón coincide varias veces en una línea?awk extraer varios grupos de cada línea

Para ilustrar, quiero buscar /Hello! (\d+)/ y utilizar los números, por ejemplo, imprimirlos o las suman, por lo que para la entrada

abcHello! 200 300 Hello! Hello! 400z3 
ads 
Hello! 0 

Si decidí imprimirlos, esperaría la salida del

200 
400 
0 
+0

para los empleados de Google: cuenta que con 'gawk', aka. "GNU awk", puedes hacer lo que dice el título (no la pregunta) en una línea (por ejemplo, a través de tuberías): '| gawk -v RS = '' '{imprimir gensub (/()() /, "\\ 1 \\ 2", "g"); } '': D Esto admite multilínea (debido a los' -v RS =' '') y subgrupos coincidentes (debido al uso de' gensub' de gawk) !!! – Andrew

Respuesta

10

Esta es una sintaxis sencilla, y cada awk (nawk, mawk, gawk, etc) puede usar esto

{ 
    while (match($0, /Hello! [0-9]+/)) { 
     pattern = substr($0, RSTART, RLENGTH); 
     sub(/Hello! /, "", pattern); 
     print pattern; 
     $0 = substr($0, RSTART + RLENGTH); 
    } 
} 
1

awk GNU

awk 'BEGIN{ RS="Hello! ";} 
{ 
    gsub(/[^0-9].*/,"",$1) 
    if ($1 != ""){ 
     print $1 
    } 
}' file 
+0

Bueno, pero no funcionará para patrones más complejos como/([a-g] + | [h-z] +)/y coincidirá con un salto de línea. –

+0

puede dar un ejemplo.? – ghostdog74

0

Esto esSintaxisTambién funciona para los patrones cuando no hay texto fija que puede funcionar como separador de registros y no coincide con más de saltos de línea:

{ 
    pattern = "([a-g]+|[h-z]+)" 
    while (match($0, pattern, arr)) 
    { 
     val = arr[1] 
     print val 
     sub(pattern, "") 
    } 
} 
0

no hay ninguna función gawk para que coincida con el mismo patrón varias veces en una línea. A menos que sepa exactamente cuántas veces se repite el patrón.

Teniendo esto en cuenta, debe iterar "manualmente" en todas las coincidencias en la misma línea. Para su entrada ejemplo, sería:

{ 
    from = 0 
    pos = match($0, /Hello! ([0-9]+)/, val) 
    while(0 < pos) 
    { 
    print val[1] 
    from += pos + val[0, "length"] 
    pos = match(substr($0, from), /Hello! ([0-9]+)/, val) 
    } 
} 

Si el patrón deberá coincidir más de un salto de línea, usted tiene que modificar el separador de registros de entrada - RS

Cuestiones relacionadas