awk match()多个匹配

时间:2016-11-13 01:01:44

标签: awk match

我有以下内容:

echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|awk '{match($0,/ZZ:Z[^ ]*/,m); print m[0], m[1]}' 
不幸的是,

仅输出第一个条目(两个中的一个):

ZZ:Z:mus.sup 

在我看来,match()函数无法在其数组中存储多个匹配项。除非我在这里失踪了......?

如果情况确实如此,有人会建议基于awk的匹配'替代方案将允许获得两个ZZ:Z条目。请注意,每次都不在同一列(!)中找到它们 - 因此需要使用match()函数。

这里的一般想法是在相同的awk命令中获得出现在已知列位置的一些值(例如col1,col2)和一些值(根据它们的唯一签名获取" ZZ:Z" )位于未知索引列的。

此外,以下尝试 - 使用gensub()也无法输出/打印两个ZZ:Z条目,并且只识别两个中的一个(另一个在弃用倒数时...)

echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|awk '{val= gensub(/.*(ZZ:Z[^ ]*).*/,"\\1 \\2","g",$0);print val}'

这种情况下的结果是:

ZZ:Z:cas.sup

但我希望得到结果:

ZZ:Z:mus.sup ZZ:Z:cas.sup 

3 个答案:

答案 0 :(得分:2)

你刚刚调用了错误的函数,你应该使用split()而不是match()

$ echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|
awk '{split($0,t,/ZZ:Z[^ ]*/,m); print m[1], m[2]}'
ZZ:Z:mus.sup ZZ:Z:cas.sup

或按照它们在输入中出现的顺序打印任意数量的事件:

$ echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|
awk '{split($0,t,/ZZ:Z[^ ]*/,m); for (i=1; i in m; i++) print m[i]}'
ZZ:Z:mus.sup
ZZ:Z:cas.sup

使用GNU awk为第4个arg分割()就像你使用GNU awk为第3个arg匹配()。

如果你必须在非GNU awk中执行此操作,那么它只是:

$ echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|
awk '{while(match($0,/ZZ:Z[^ ]*/)) {print substr($0,RSTART,RLENGTH); $0=substr($0,RSTART+RLENGTH)}}'
ZZ:Z:mus.sup
ZZ:Z:cas.sup

答案 1 :(得分:1)

match的结果可用于获取不匹配的部分 附加匹配:

{
        for (s = $0; match(s, /ZZ:Z[^ ]*/);
            s = substr(s, RSTART + RLENGTH, length))
                printf("%s%s", s == $0 ? "" : " ", 
                    substr(s, RSTART, RLENGTH))
        print ""
}

或者,可以在唯一标识符上拆分字符串, 使用splitFS

{
        l = split($0, a, /ZZ:Z/)
        for(i = 2; i <= l; i++)
                printf("%s%s", i == 2 ? "" : " ",
                    "ZZ:Z" substr(a[i], 1, index(a[i], " ") - 1))
        print ""
}

答案 2 :(得分:0)

谢谢,上述解决方案非常棒,无论ZZ:Z条目在原始行中重复多少次,都能提供广泛的解决方案。

然而,这是我瞄准的一个班轮,这是我上面使用的错误匹配条件的修复:

echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|awk '{val= gensub(/.*(ZZ:Z[^ ]*).*(ZZ:Z[^ ]*).*/,"\\1 \\2","g");print val}'

输出:

ZZ:Z:mus.sup ZZ:Z:cas.sup

此外,这是解决方案 - 使用awk的match():

echo AS:i:0  UQ:i:0  ZZ:Z:mus.sup  NM:i:0  MD:Z:50  ZZ:Z:cas.sup  CO:Z:endOfLine|awk '{match($0,/.*(ZZ:Z[^ ]*).*(ZZ:Z[^ ]*).*/,m); print m[1], m[2]}'