AWK:从线条模式访问捕获的组

如果我有一个awk命令

pattern { ... }

和模式使用捕获组,我怎么能访问字符串,所以在块捕获?

221365 次浏览

那是在回忆的小路上漫步……

很久以前,我用perl替换了awk。

显然,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

您也可以在vanilla awk中模拟捕获,不需要扩展。这并不直观:

< p >步骤1。使用gensub将匹配的字符串与一些不出现在字符串中的字符包围起来。 步骤2。对角色使用分裂。 步骤3。拆分数组中的每一个其他元素都是捕获组
$ echo 'ab cb ad' | awk '{ split(gensub(/a./,SUBSEP"&"SUBSEP,"g",$0),cap,SUBSEP); print cap[2]"|" cap[4] ; }'
ab|ad

你可以使用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/

这是我一直需要的东西,所以我为它创建了一个bash函数。这是基于格伦·杰克曼的答案。

定义

将此添加到您的.bash_profile等。

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

使用

捕获文件中每一行的正则表达式

$ cat filename | regex '.*'

为文件中的每一行捕获第一个正则表达式捕获组

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

我在提出一个bash函数来包装Peter Tillemans的答案时遇到了一些困难,但下面是我想到的:

< p > regex函数 { Perl -n -e "/$1/ &&Printf \"%s\n\", " $1 " } < / p >

对于下面的正则表达式参数,我发现这比opsb基于awk的bash函数工作得更好,因为我不想打印“ms”。

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

我认为gawk match()-to-array仅用于捕获组的第一个实例。

如果您想要捕获多个东西,并对它们执行任何复杂的操作,那么可能

gawk 'BEGIN { S = SUBSEP
} {
nx=split(gensub(/(..(..)..(..))/,
"\\1"(S)"\\2"(S)"\\3", "g", str),
arr, S)
for(x in nx) { perform-ops-over arr[x] } }'

这样你既不受gensub()的约束(它限制了修改的复杂性),也不受match()的约束。

通过纯试错,我注意到在unicode模式下gawk的一个警告:对于一个有效的unicode字符串뀇꿬,包含下面列出的6个八进制代码:

场景1:匹配单个字节很好,但也会向您报告多字节的RSTART为1,而不是字节级的答案为2。它也不会提供有关207年\是第一个延续字节还是第二个延续字节的信息,因为RLENGTH在这里总是1。

$ gawk 'BEGIN{ print match("\353\200\207\352\277\254", "\207") }'
$ 1

场景2:Match也适用于这样的unicode无效模式

$ gawk 'BEGIN{ match("\353\200\207\352\277\254", "\207\352");
$                print RSTART, RLENGTH }'
$ 1 2

场景3:您可以针对unicode非法字符串检查模式是否存在(300年\ \ xC0对于所有可能的字节对都是UTF8-invalid)

$ gawk 'BEGIN{ print ("\300\353\200\207\352\277\254" ~ /\200/) }'
$ 1

场景4/5/6:错误消息将显示(a)带有unicode-invalid字符串的match(),任意参数为unicode-invalid/incomplete的index()

$ gawk 'BEGIN{ match("\300\353\200\207\352\277\254", "\207\352"); print RSTART, RLENGTH }' gawk: cmd. line:1: warning: Invalid multibyte data detected. There may be a mismatch between your data and your locale. 2 2


$ gawk 'BEGIN{ print index("\353\200\207\352\277\254", "\352") }' gawk: cmd. line:1: warning: Invalid multibyte data detected. There may be a mismatch between your data and your locale. 0


$ gawk 'BEGIN{ print index("\353\200\207\352\277\254", "\200") }' gawk: cmd. line:1: warning: Invalid multibyte data detected. There may be a mismatch between your data and your locale. 0