Вопрос по grouping, awk, regex – awk извлекает несколько групп из каждой строки

8

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

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

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

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

200
400
0
Для Google: обратите внимание, что сgawkака. & quot; GNU awk & quot ;, на самом деле вы можете делать то, что говорит заголовок (не вопрос), в одну строку (например, через. piping):| gawk -v RS='' '{ print gensub(/()()/, "\\1\\2", "g"); }' : D Это поддерживает многострочность (из-за-v RS='') и соответствующие подгруппы (из-за использования gawk 'sgensub)!!! Andrew

Ваш Ответ

4   ответа
11

Это простой синтаксис, и каждый awk (nawk, mawk, gawk и т. Д.) Может использовать это.

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

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

 {
     pattern = "([a-g]+|[h-z]+)"
     while (match($0, pattern, arr))
     {
         val = arr[1]
         print val
         sub(pattern, "")
     }
 }
Тотsub в конце имеет огромное значение! К сожалению, мне потребовалось некоторое время, чтобы попробовать это ... Спасибо!
0

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

Имея это, вы должны выполнить итерацию & quot; вручную & quot; на всех матчах в одной строке. Для вашего примера ввода это будет:

{
  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

1

GNU awk

awk 'BEGIN{ RS="Hello! ";}
{
    gsub(/[^0-9].*/,"",$1)
    if ($1 != ""){ 
        print $1 
    }
}' file
Можете ли вы привести пример.?
Это хорошо, но не будет работать для более сложных шаблонов, таких как / ([a-g] + | [h-z] +) /, и будет совпадать с переводом строки. Adrian Panasiuk

Похожие вопросы