awk извлекает несколько групп из каждой строки - PullRequest
8 голосов
/ 12 июля 2009

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

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

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

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

200
400
0

Ответы [ 4 ]

11 голосов
/ 13 июля 2009

Это простой синтаксис, и каждый 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 голосов
/ 12 июля 2009

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

 {
     pattern = "([a-g]+|[h-z]+)"
     while (match($0, pattern, arr))
     {
         val = arr[1]
         print val
         sub(pattern, "")
     }
 }
1 голос
/ 12 июля 2009

GNU awk

awk 'BEGIN{ RS="Hello! ";}
{
    gsub(/[^0-9].*/,"",$1)
    if ($1 != ""){ 
        print $1 
    }
}' file
0 голосов
/ 27 июля 2009

Нет функции 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...