Если у меня есть команда awk
pattern { ... }
и шаблон использует группу захвата, как я могу получить доступ к строке, захваченной в блоке?
Если у меня есть команда awk
pattern { ... }
и шаблон использует группу захвата, как я могу получить доступ к строке, захваченной в блоке?
Это была прогулка по полосе памяти...
Я давно заменил awk на perl.
Очевидно, что механизм регулярного выражения AWK не отображает его группы.
вы можете использовать что-то вроде:
perl -n -e'/test(\d+)/ && print $1'
флаг -n вызывает perl для цикла по каждой строке, например awk.
С помощью 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
.
Это то, что мне нужно все время, поэтому я создал для него функцию bash. Это основано на ответе Гленна Джекмана.
Добавьте это в свой .bash_profile и т.д.
function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; }
Захват регулярного выражения для каждой строки в файле
$ cat filename | regex '.*'
Захват 1-й группы захвата регулярных выражений для каждой строки в файле
$ cat filename | regex '(.*)' 1
Вы можете использовать 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/
Вы можете имитировать захват в ванильном 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
Я немного боролся с приходом функции bash, которая обертывает ответ Питера Тиллеманса, но вот что я придумал:
функция regex { perl -n -e "/$1/& printf \" % s\n\ "," '$ 1' }
Я нашел, что это работает лучше, чем opsb awk-based bash функция для следующего аргумента регулярного выражения, потому что я не хочу, чтобы "ms" печаталась.
'([0-9]*)ms$'