2009-07-12 25 views
8

Come si esegue un'azione su tutti i gruppi corrispondenti quando il modello corrisponde più volte in una riga?awk estrae più gruppi da ciascuna riga

Per illustrare, voglio cercare /Hello! (\d+)/ e utilizzare i numeri, per esempio, stamparli o sommare loro, così per l'ingresso

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

Se ho deciso di stamparli, mi aspetto l'uscita del

200 
400 
0 
+0

Per Googler: notare che con 'gawk', alias. "GNU awk", puoi effettivamente fare ciò che dice il titolo (non la domanda) in una riga (ad esempio tramite piping): '| gawk -v RS = '' '{print gensub (/()() /, "\\ 1 \\ 2", "g"); } '': D Questo supporta multi-line (a causa di' -v RS =' '') e corrispondenti sottogruppi (a causa dell'uso di' gensub' di gawk) !!! – Andrew

risposta

10

Questa è una sintassi semplice, ed ogni awk (nawk, mawk, gawk, ecc) può usare questo

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

GNU awk

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

Bello, ma non funzionerà per motivi più complessi come/([a-g] + | [h-z] +)/e corrisponderà a un avanzamento di riga. –

+0

puoi fornire un esempio? – ghostdog74

0

Questo èSintassi. Funziona anche per i modelli quando non c'è testo fisso che può funzionare come un separatore di record e non corrisponde più di linefeeds:

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

Non esiste alcuna funzione di gawk per abbinare lo stesso motivo più volte in una riga. A meno che tu non sappia esattamente quante volte il modello si ripete.

Avendo questo, è necessario ripetere "manualmente" su tutte le partite nella stessa riga. Per il vostro ingresso esempio, sarebbe:

{ 
    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) 
    } 
} 

Se il modello deve corrispondere a più di un avanzamento riga, è necessario modificare il separatore di record in ingresso - RS

Problemi correlati