2016-11-13 368 views
1

我有以下几点: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 '{match($0,/ZZ:Z[^ ]*/,m); print m[0], m[1]}' 

不幸的是只输出第一项(出2):

ZZ:Z:mus.sup 

在我看来这门亲事()函数不能在其数组中存储多个匹配项。除非我在这里错过...?

如果确实如此,有人会好好建议一个基于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 

回答

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第四届ARG分裂()就像你正在使用GNU awk来匹配第三个参数()。

如果你不得不这样做是在非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 
+0

你能否检查一下你的解决方案,这可能只是在我的最后一个问题,但我得到一个错误信息: “awk:致命:4是无效的作为拆分参数的数量” – Roy

+0

您需要使用GNU awk 4.0或更近期。如果您使用的版本比以前版本要高,那么您需要尽快更新,因为4.0版本已经存在了5年以上(2011年6月发布了4.0.0,现在版本为4.1.4!),并且您错过了吨非常有用的功能和错误修复(请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Feature-History) –

1

match结果可以用来获得不一致部分为 附加匹配:

{ 
     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 "" 
} 
+0

这是一个整洁的通用解决方案,可以与尽可能多的出场工作,因为他们来了 - 很不错的! tnx – Roy

0

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

可替换地,串可在唯一的标识符, 或者与splitFS被分割

谢谢,上述解决方案非常好,并且为问题提供了广泛的解决方案 - 无论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的匹配():

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]}' 
+0

不,这些都不是正确的解决方案。请参阅http://stackoverflow.com/a/40574948/1745001。 –