2013-03-02 54 views
0

我想在linux shell腳本中有條件地替換某些列。Linux:如果同一行中的另一列以特定字符開始/結尾,請替換特定列

MYDATA是

ID   chr pos ver 
rs1234  1 12312 b1 
rs1245  1 21312 b1 
chr1:7576:D 1 22312 b1 
rs1002  1 34535 b1 
chr1:2434:D 1 34534 b1 
MER:1222 1 54645 b1 
rs2123  1 45645 b1 

和我想和「NA」,如果第一列開始以「MER」或「d」端來代替第三列。 因此,作爲最終文件將是如下

ID   chr pos ver 
rs1234  1 12312 b1 
rs1245  1 21312 b1 
chr1:7576:D 1 **NA** b1 
rs1002  1 34535 b1 
chr1:2434:D 1 **NA** b1 
MER:1222 1 **NA** b1 
rs2123  1 45645 b1 

回答

0

可以按如下方式與awk實現這一目標:

# awk '{if(NR!=1&&($1~/^MER/||$1~/D$/)){$3="N/A"} print $0}' INPUT > OUTPUT 

這讓下面的輸出,使用您的樣本數據:

ID   chr pos ver 
rs1234  1 12312 b1 
rs1245  1 21312 b1 
chr1:7576:D 1 N/A b1 
rs1002  1 34535 b1 
chr1:2434:D 1 N/A b1 
MER:1222 1 N/A b1 
rs2123  1 45645 b1 

如果要保留格式並且列的寬度固定,則可以使用printf語句:

# awk '{if(NR!=1&&($1~/^MER/||$1~/D$/)){$3="N/A"} printf("%-As %Bs %Cs %Ds\n",$1,$2,$3,$4)}' INPUT > OUTPUT 

用代表期望列寬度的整數代替A,B,C和D.例如:

# awk '{if(NR!=1&&($1~/^MER/||$1~/D$/)){$3="N/A"} printf("%-11s %1s %5s %2s\n",$1,$2,$3,$4)}' INPUT > OUTPUT 

這給:

ID   chr pos ver 
rs1234  1 12312 b1 
rs1245  1 21312 b1 
chr1:7576:D 1 N/A b1 
rs1002  1 34535 b1 
chr1:2434:D 1 N/A b1 
MER:1222  1 N/A b1 
rs2123  1 45645 b1 
0

下面是與sed

sed -e 's/\(\(MER:[0-9]\+\|[0-9:]D\)\s\+[0-9]\+\s\+\)[0-9]\+\(.*\)/\1**NA**\3/g' INPUTFILE 

的解決方案產生

ID   chr pos ver 
rs1234  1 12312 b1 
rs1245  1 21312 b1 
chr1:7576:D 1 **NA** b1 
rs1002  1 34535 b1 
chr1:2434:D 1 **NA** b1 
MER:1222 1 **NA** b1 
rs2123  1 45645 b1 

awk是親可以順利走到這裏。或者perl。

0

下面是使用一個Perl一行代碼的解決方案:

perl -pe 's/^(MER:.+?|.+?:D)(\s+\d+\s+)(\d+)(.*)$/$1$2**NA**$4/' foo.txt 

添加-i選項Perl來直接修改原文件。

這裏是上面的例子中的一個更詳細的分類:

您可以搜索並與S /匹配/替換/語法替換...

s/^(MER:.+?|.+?:D)(\s+\d+\s+)(\d+)(.*)$/$1$2**NA**$4/ 
^^         ^  ^

括號是用來捕捉組匹配用於替換。

s/^(MER:.+?|.+?:D)(\s+\d+\s+)(\d+)(.*)$/$1$2**NA**$4/ 
    ^_____________^^_________^^___^^__^ 
     $1   $2  $3 $4 

只有在正則表達式匹配時纔會進行替換,因此括號中的第一個組確定了您的情況下的匹配。由於您想從MER:開始或以:D結尾,因此|符號用於表示「或」。

正則表達式是搜索和替換的強大方式,並且在許多工具和語言中都受支持。值得在線查找教程以更好地理解此語法。

相關問題