2016-08-16 66 views
2

我有一個長文件名爲test,看起來如下工作:如何只替換文件中的特定列?

AHAP USA|NIS00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR 
KJJLIL123124%|NIS00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR 
ASFASS9992|NIS00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY 

我需要進行替換字符串「NIS」到「NIX」,但是,我只需要在第二個欄來實現這一這是由管道字符分隔,我的數據分隔符是管道「|」,我有幾列,總共七個,我只是想做第二個替換。

我想:

$ sed s/NIS/NIX/g test 
AHAP USA|NIX00333|+NULL|NIXGOOGLE|NIX00005|*binary|NIXCAR 
KJJLIL123124%|NIX00160|+NULL|NIXFACEBOOK|NIX00006|*binary|NIXBUR 
ASFASS9992|NIX00164|+NULL|NIXTABLE|NIX00008|*binary|NIXFANCY 

但它影響到所有與該字符串匹配的列:NIS,並更改爲NIX,我只是想影響第二列,我需要的輸出將是:

AHAP USA|NIX00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR 
KJJLIL123124%|NIX00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR 
ASFASS9992|NIX00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY 

我真的很感謝這個問題的幫助,謝謝任何如何。

回答

3

如果您在列的問題,不要使用awk讓他們更好的,本地控制:

$ awk 'BEGIN {FS=OFS="|"}{gsub("NIS","NIX",$2)}1' file 
AHAP USA|NIX00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR 
KJJLIL123124%|NIX00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR 
ASFASS9992|NIX00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY 

此執行gsub()更換的2 第二|基於領域。完成此替換後,1將觸發awk的默認操作,其中包含打印$0,其中包含完整(更新)的記錄。

+0

謝謝,我真的很感謝這個建議,我會考慮用awk代替sed來處理列,只是多一個問題,代替awk的替換是什麼,我的意思是如果你使用sed,你可以使用sed -i來實現在同一個文件中改變,你知道awk的等價物嗎? – neo33

+0

@ neo33你可以使用GNU awk 4.1.0中的'-i inplace'。否則,訣竅始終是'awk'...'file> tmp_file && mv tmp_file file'。所有這些都在[awk save modifications inplace]中描述(http://stackoverflow.com/a/16529730/1983854)。 – fedorqui

+1

是的,我非常感謝支持,這真的很有幫助。 – neo33

2

一個sed溶液:

$ sed 's/^\([^|]*|[^|]*\)NIS/\1NIX/' infile 
AHAP USA|NIX00333|+NULL|NISGOOGLE|NIS00005|*binary|NISCAR 
KJJLIL123124%|NIX00160|+NULL|NISFACEBOOK|NIS00006|*binary|NISBUR 
ASFASS9992|NIX00164|+NULL|NISTABLE|NIS00008|*binary|NISFANCY 

正則表達式,分裂:

^   # Start of line anchor 
\(  # Start of capture gruop 
    [^|]* # Characters other than pipe - first column 
    |  # Column separator between first and second column 
    [^|]* # Characters other than pipe - first part of second column 
\)   # End of capture group 
NIS  # What we actually want to replace 

這具有一個限制,因爲它僅替換的NIS在第二列中的第一次出現。這個例子輸入沒有任何更多的,但如果它確實,我們可以使用條件分支,只要它的格局變化空間重複替代:

sed ' 
:a 
s/^\([^|]*|[^|]*\)NIS/\1NIX/ 
ta' infile 

:a是跳轉到標籤,ta是條件分支命令(「如果替換做了某事,則跳轉到:a」)。

作爲一個班輪:

sed ':a;s/^\([^|]*|[^|]*\)NIS/\1NIX/;ta' infile 

BSD的sed(如在Mac OS中)會抱怨標籤沒有跟着一個換行符,所以我們可以改寫爲

sed -e ':a' -e 's/^\([^|]*|[^|]*\)NIS/\1NIX/;ta' infile 
+0

哇這真的很有幫助我的第一個方法是在sed中思考,但是這是使用正則表達式的好方法,雖然對於這個特定的任務有點更容易使用awk我的意思是處理列, – neo33

+1

@ neo33在Ed出現之前,讓我自己說一下:在99.9%的情況下,awk比sed更快,更強大,更簡潔。有人說,sed應該被忽略,因爲它已經被awk所取代 - 有些人(像我一樣)主要懷念懷舊的原因; –

+0

是的,我明白,也許是由於sed比awk更受歡迎然而,對於瞭解更多關於awk的知識絕對是一個非常好的主意,感謝這個建議,我感謝支持。 – neo33

相關問題