awk извлекает несколько групп из каждой строки
Как выполнить действие для всех подходящих групп, если шаблон совпадает несколько раз в строке?
Чтобы проиллюстрировать, я хочу найти /Hello! (\d+)/
и использовать числа, например, распечатать их или сложить их, так что для ввода
abcHello! 200 300 Hello! Hello! 400z3
ads
Hello! 0
Если бы я решил распечатать их, я бы ожидал вывод
200
400
0
4 ответа
Это простой синтаксис, и каждый 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);
}
}
Это gawk
синтаксис. Это также работает для шаблонов, когда нет фиксированного текста, который может работать как разделитель записей и не совпадает с переводом строки:
{
pattern = "([a-g]+|[h-z]+)"
while (match($0, pattern, arr))
{
val = arr[1]
print val
sub(pattern, "")
}
}
GNU awk
awk 'BEGIN{ RS="Hello! ";}
{
gsub(/[^0-9].*/,"",$1)
if ($1 != ""){
print $1
}
}' file
Не существует функции 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