您可以製作一個awk單行程序,用於拆分包含冒號的字段,並僅用一個子字段替換那些空白分隔的字段。類似這樣的:
$ cat inp.txt
position1 456754 0/1:170,167:339:99:3370,0,3372:50:99:0.496 ./.:.:.:.:.:.:.:.
position2 456759 0/1:161,162:325:99:3266,0,3215:50:99:0.502 ./.:.:.:.:.:.:.:.
$ awk '{ for(i=1; i<=NF; i++) { if($i~/:/){split($i,a,":"); $i=a[1] } } } 1' inp.txt
position1 456754 0/1 ./.
position2 456759 0/1 ./.
for
循環遍歷字段列表。然後,如果有任何字段包含冒號,我們將該字段放入一個數組(a
),並用第一個元素(a[1]
)替換整個字段($i
)。命令字符串末尾的1
對於「打印此行」是短暫的,無論是否進行了任何替換,這都會發生。
如果你想在某個CPU爲代價的一個簡單的awk腳本,這也應該工作:
$ awk '{ for(i=1; i<=NF; i++) { split($i,a,":"); $i=a[1] } } 1' inp.txt
這只是消除了if()
條件,這樣對每行每一個領域,你將取代領域與「第一個冒號定界的子領域」。對於沒有冒號的字段,這會將字段替換爲它自己。
或者,對於穩健的解決方案少,你可以使用sed
:
$ sed -r -e 's/(:[^ ]*)(|$)/\2/g' inp.txt
position1 456754 0/1 ./.
position2 456759 0/1 ./.
該解決方案的行內讀取和替代字符串,而不是解析領域的awk在做事情的方式。它可能和awk解決方案一樣可靠,雖然可能稍微不靈活(例如awk會讓你採用不同的子域,而sed解決方案則不然)。
注意替換命令結束時的g
。這告訴sed執行「全局」替代,而不僅僅是搜索正則表達式的第一個匹配。
此解決方案使用-r
選項告訴sed使用擴展正則表達式。如果您使用的是OS X或某些(較早)的BSD unix版本,請使用-E
選項。在其他情況下,您可能必須將其轉換爲BRE。
只是兩種方法。我相信在其他答案中會出現更多。