2009-07-12 15 views
8

Jak wykonać akcję na wszystkich pasujących grupach, gdy wzorzec pasuje wiele razy w linii?awk wyodrębnić wiele grup z każdej linii

Aby zilustrować, chcę szukać /Hello! (\d+)/ i używać liczb, na przykład wydrukować je lub suma ich, więc na wejściu

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

Gdybym zdecydował się wydrukować je, bym oczekiwać wyjście

200 
400 
0 
+0

dla Googlersami: pamiętać, że z 'gawk', aka. "GNU awk", możesz faktycznie zrobić to, co tytuł mówi (nie pytanie) w jednym wierszu (np. Przez. Piping): '| gawk -v RS = '' '{print gensub (/()() /, "\\ 1 \\ 2", "g"); } '': D Obsługuje wiele linii (ze względu na' -v RS =' '') i pasujące podgrupy (z powodu używania gawk' gensub') !!! – Andrew

Odpowiedz

10

To prosta składnia, a każdy awk (nawk, mawk, gawk itp) może tego użyć.

{ 
    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

Przyjemnie, ale nie będzie działać dla bardziej złożonych wzorów, takich jak/([a-g] + | [h-z] +)/i będzie pasować do linii. –

+0

możesz podać przykład.? – ghostdog74

0

to gawk składnia. Działa również dla wzorców, gdy nie ma stały tekst, który może pracować jako separator rekordu i nie zgadza się na karetki:

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

Brak funkcji gawk do wielokrotnego dopasowania tego samego wzoru w linii. O ile nie wiesz dokładnie, ile razy wzór się powtarza.

Mając to, musisz powtórzyć "ręcznie" na wszystkich meczach w tej samej linii. Na swoim przykładzie wejścia, byłoby:

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

Jeżeli wzorzec powinien dopasować się znak nowego wiersza, trzeba zmodyfikować separator rekordu wejściowego - RS