2009-07-12 2 views
8

Как выполнить действие во всех сопоставимых группах, когда шаблон соответствует несколько раз в строке?awk извлекает несколько групп из каждой строки

Для иллюстрации я хочу найти /Hello! (\d+)/ и использовать цифры, например, распечатать их или суммировать их, так что для ввода

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

Если я решил напечатать их, я бы ожидать, выход

200 
400 
0 
+0

Для Googlers: обратите внимание, что с 'gawk', ака. «GNU awk», вы действительно можете сделать то, что говорит название (не вопрос) в одной строке (например, через.): '| gawk -v RS = '' '{print gensub (/()() /, "\\ 1 \\ 2", "g"); } '': D Это поддерживает многострочный (из-за' -v RS =' '') и соответствующих подгрупп (из-за использования gawk' gensub') !!! – Andrew

ответ

10

Это простой синтаксис, и каждый AWK (nawk, Мок, поглазеть, и т.д.) может использовать это.

{ 
    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

Приятно, но не будет работать для более сложных шаблонов, таких как/([a-g] + | [h-z] +)/и будет соответствовать по строке. –

+0

вы можете привести пример.? – ghostdog74

0

Это gawk синтаксис. Он также работает для моделей, когда нет фиксированного текста, который может работать как разделитель записей и не соответствует более пробельным символам:

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

Нет функции gawk, которая бы соответствовала одному и тому же шаблону несколько раз в строке. Если вы точно не знаете, сколько раз образец повторяется.

При этом вам необходимо выполнить итерацию «вручную» во всех матчах в одной строке. Для примера входных данных, это было бы:

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

Если шаблон должен соответствовать над переводом строки, вы должны изменить входной разделитель - RS

Смежные вопросы