Awk: доступ к захваченной группе из шаблона строки

Если у меня есть команда awk

pattern { ... }

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

Ответ 1

Это была прогулка по полосе памяти...

Я давно заменил awk на perl.

Очевидно, что механизм регулярного выражения AWK не отображает его группы.

вы можете использовать что-то вроде:

perl -n -e'/test(\d+)/ && print $1'

флаг -n вызывает perl для цикла по каждой строке, например awk.

Ответ 2

С помощью gawk вы можете использовать функцию match для записи групп в скобки.

gawk 'match($0, pattern, ary) {print ary[1]}' 

Пример:

echo "abcdef" | gawk 'match($0, /b(.*)e/, a) {print a[1]}' 

выводит cd.

Обратите внимание на конкретное использование gawk, которое реализует эту функцию.

Для переносной альтернативы вы можете добиться аналогичных результатов с помощью match() и substr.

Пример:

echo "abcdef" | awk 'match($0, /b[^e]*/) {print substr($0, RSTART+1, RLENGTH-1)}'

выходы cd.

Ответ 3

Это то, что мне нужно все время, поэтому я создал для него функцию bash. Это основано на ответе Гленна Джекмана.

Определение

Добавьте это в свой .bash_profile и т.д.

function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; }

Использование

Захват регулярного выражения для каждой строки в файле

$ cat filename | regex '.*'

Захват 1-й группы захвата регулярных выражений для каждой строки в файле

$ cat filename | regex '(.*)' 1

Ответ 4

Вы можете использовать GNU awk:

$ cat hta
RewriteCond %{HTTP_HOST} !^www\.mysite\.net$
RewriteRule (.*) http://www.mysite.net/$1 [R=301,L]

$ gawk 'match($0, /.*(http.*?)\$/, m) { print m[1]; }' < hta
http://www.mysite.net/

Ответ 5

Вы можете имитировать захват в ванильном awk тоже без расширений. Это не интуитивно, хотя:

Шаг 1. Используйте gensub для соответствия совпадений с некоторым символом, который не отображается в вашей строке. Шаг 2. Используйте split для символа. шаг 3. Каждый другой элемент в разбитом массиве - ваша группа захвата.

$ echo 'ab cb ad' | awk '{ split(gensub(/a./,SUBSEP"&"SUBSEP,"g",$0),cap,SUBSEP); print cap[2]"|" cap[4] ; }'
ab|ad

Ответ 6

Я немного боролся с приходом функции bash, которая обертывает ответ Питера Тиллеманса, но вот что я придумал:

функция regex {     perl -n -e "/$1/& printf \" % s\n\ "," '$ 1' }

Я нашел, что это работает лучше, чем opsb awk-based bash функция для следующего аргумента регулярного выражения, потому что я не хочу, чтобы "ms" печаталась.

'([0-9]*)ms$'