2016-11-13 286 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。 –