Иногда (в простых случаях) можно настроить разделитель полей ( FS) и выбрать то, что вы хотите сопоставить с $field. Преформатирование ввода также может помочь.
Видимо кто-то не согласен. Эта веб-страница с 2005 года: tek-tips.com/faqs.cfm?fid=5674 Это подтверждает, что вы не можете повторно использовать соответствующие группы в awk.
Питер Тиллеманс
3
Я предпочитаю «perl -n -p -e ...», а не awk для почти всех вариантов использования, так как он более гибкий, более мощный и, на мой взгляд, имеет более разумный синтаксис.
Питер Тиллеманс
15
gawk! = awk. Это разные инструменты и gawkпо умолчанию недоступны в большинстве мест.
Оли
6
ОП специально попросил решение awk, поэтому я не думаю, что это ответ.
Джоппе
6
@Joppe, вы не можете дать решение awk, если нет решения. В строке 3 я объясняю, что AWK не поддерживает группы захвата, и я дал альтернативу, которую ОП, очевидно, оценил, потому что этот ответ был принят. Как я мог лучше ответить на этот вопрос?
Питер Тиллеманс
335
С 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.
@bfontaine Может ли grep -oвыводить захваченные группы?
Olle Härstedt
1
@ OlleHärstedt Нет, не мог. Он охватывает только ваш вариант использования, когда у вас нет групп захвата. В этом случае это становится уродливым с цепями grep -o.
Эд Мортон: это заслуживает ответа на высшем уровне, я бы сказал. редактировать: хм ... это печатает RewriteRule (.*) http://www.mysite.net/$для меня, что больше, чем подгруппа.
Вы также можете смоделировать захват в vanilla awk без расширений. Это не интуитивно, хотя:
шаг 1. используйте gensub, чтобы окружить совпадения каким-либо символом, который не появляется в вашей строке. Шаг 2. Используйте раскол против персонажа. Шаг 3. Каждый другой элемент в расщепленном массиве является вашей группой захвата.
Я почти уверен, что gensubэто gawkособая функция. Что вы получаете от вашего awk, если вы печатаете awk --version; -?). Всем удачи.
Shellter
6
Я полностью уверен, что gensub - это gawk-ism, хотя в BusyBox awk он также есть. Этот ответ также может быть реализован с использованием gsub, однако:echo 'ab cb ad' | awk '{gsub(/a./,SUBSEP"&"SUBSEP);split($0,cap,SUBSEP);print cap[2]"|"cap[4]}'
dubiousjim
3
gensub () - расширение gawk, в руководстве gawk об этом ясно сказано. Другие варианты awk могут также реализовать его, но это все еще не POSIX. Попробуйте gawk --posix '{gsub (...)}', и он будет жаловаться
MestreLion
2
@MestreLion, вы имеете в виду, что он будет жаловаться gawk --posix '{gensub(...)}'.
dubiousjim
1
Несмотря на то, что вы ошиблись в POSIX awk сgensub функцию, ваш пример был применен к очень ограниченному сценарию: весь шаблон сгруппирован, он не может соответствовать чему-то похожему на все, key=(value)когда я хочу извлечь только valueчасти.
мяу
2
Я немного изо всех сил пытался придумать функцию bash, которая заключает в себе ответ Питера Тиллемана, но вот что я придумал:
function regex {perl -n -e "/ $ 1 / && printf \"% s \ n \ "," '$ 1'}
Я обнаружил, что это работает лучше, чем основанная на awk функция opsb для следующего аргумента регулярного выражения, потому что я не хочу, чтобы выводился «ms».
Я предпочитаю это решение, так как вы можете видеть части группы, которые ограничивают захват, а также опускают их. Однако кто-то может объяснить, как это работает? Я не могу заставить этот синтаксис Perl работать должным образом в BASH, потому что я не очень хорошо понимаю его - особенно двойные / одинарные кавычки$1
Demis
Это не то, что я делал до или после этого, но, оглядываясь назад, он объединяет две строки, первая строка в двойных кавычках (эта первая строка содержит встроенные двойные кавычки, экранированные обратной косой чертой), а вторая строка в одинарных кавычках , Затем результат этой конкатенации передается в качестве аргумента в perl -e. Также вам нужно знать, что первый $ 1 (тот, что в двойных кавычках) заменяется первым аргументом функции, а второй $ 1 (тот, что в одинарных кавычках) остается нетронутым. Смотрите этот пример
Wytten
Понятно, теперь это имеет больше смысла. Так где же в команде perl определение соответствия регулярному выражению / захвата группы? Я вижу, вы написали '([0-9]*)ms$'- это предоставляется в качестве аргумента (а в строке другой аргумент)? И вывод из команды perl -eвставляется в printfкоманду bash , чтобы заменить %s, верно? Спасибо, я надеюсь использовать это.
Демис
1
Вы передаете регулярное выражение, заключенное в одинарные кавычки, в качестве единственного аргумента для функции regex bash. Пример
FS
) и выбрать то, что вы хотите сопоставить с$field
. Преформатирование ввода также может помочь.gawk
(так как он используетgensub
).Ответы:
Это была прогулка по переулку памяти ...
Я заменил awk на perl очень давно.
Очевидно, механизм регулярных выражений AWK не захватывает его группы.
Вы можете рассмотреть возможность использования чего-то вроде:
флаг -n заставляет perl перебирать каждую строку, как это делает awk.
источник
gawk
! =awk
. Это разные инструменты иgawk
по умолчанию недоступны в большинстве мест.С gawk вы можете использовать
match
функцию для захвата заключенных в скобки групп.пример:
выходы
cd
.Обратите внимание на конкретное использование gawk, которое реализует данную функцию.
Для портативной альтернативы вы можете достичь аналогичных результатов с
match()
иsubstr
.пример:
выходы
cd
.источник
Это то, что мне нужно все время, поэтому я создал для него функцию bash. Это основано на ответе Гленна Джекмана.
Определение
Добавьте это к вашему .bash_profile и т. Д.
использование
Записать регулярное выражение для каждой строки в файле
Захват 1-й группы захвата регулярных выражений для каждой строки в файле
источник
grep -o
?grep -o
выводить захваченные группы?grep -o
.Вы можете использовать GNU awk:
источник
awk 'match($0, /.*(http.*?)\$/) { print substr($0,RSTART,RLENGTH) }'
RewriteRule (.*) http://www.mysite.net/$
для меня, что больше, чем подгруппа.RSTART
иRLENGTH
ссылается на подстроку, соответствующую шаблонуВы также можете смоделировать захват в vanilla awk без расширений. Это не интуитивно, хотя:
шаг 1. используйте gensub, чтобы окружить совпадения каким-либо символом, который не появляется в вашей строке. Шаг 2. Используйте раскол против персонажа. Шаг 3. Каждый другой элемент в расщепленном массиве является вашей группой захвата.
источник
gensub
этоgawk
особая функция. Что вы получаете от вашего awk, если вы печатаетеawk --version
; -?). Всем удачи.echo 'ab cb ad' | awk '{gsub(/a./,SUBSEP"&"SUBSEP);split($0,cap,SUBSEP);print cap[2]"|"cap[4]}'
gawk --posix '{gensub(...)}'
.gensub
функцию, ваш пример был применен к очень ограниченному сценарию: весь шаблон сгруппирован, он не может соответствовать чему-то похожему на все,key=(value)
когда я хочу извлечь толькоvalue
части.Я немного изо всех сил пытался придумать функцию bash, которая заключает в себе ответ Питера Тиллемана, но вот что я придумал:
Я обнаружил, что это работает лучше, чем основанная на awk функция opsb для следующего аргумента регулярного выражения, потому что я не хочу, чтобы выводился «ms».
источник
$1
'([0-9]*)ms$'
- это предоставляется в качестве аргумента (а в строке другой аргумент)? И вывод из командыperl -e
вставляется вprintf
команду bash , чтобы заменить%s
, верно? Спасибо, я надеюсь использовать это.