2010-06-24 158 views
6

我有一個看起來像這樣的數據線:刪除部分字符串使用sed

sp_A0A342_ATPB_COFAR_6_+_contigs_full.fasta 
sp_A0A342_ATPB_COFAR_9_-_contigs_full.fasta 
sp_A0A373_RK16_COFAR_10_-_contigs_full.fasta 
sp_A0A373_RK16_COFAR_8_+_contigs_full.fasta 
sp_A0A4W3_SPEA_GEOSL_15_-_contigs_full.fasta 

如何使用sed第4列(_分隔)每行之後刪除部分字符串。 最後產生:

sp_A0A342_ATPB_COFAR 
sp_A0A342_ATPB_COFAR 
sp_A0A373_RK16_COFAR 
sp_A0A373_RK16_COFAR 
sp_A0A4W3_SPEA_GEOSL 

回答

19

cut是一個更適合。

cut -d_ -f 1-4 old_file 

這僅僅意味着使用_作爲分隔符,並保留字段1-4。

如果你堅持sed

sed 's/\(_[^_]*\)\{4\}$//' 

這左手邊匹配一組恰好四個重複,組成一個下劃線後跟0或多個非下劃線的。在那之後,我們必須處於最後。這全部被沒有取代。

1
sed -e 's/_[0-9][0-9]*_[+-]_contigs_full.fasta$//g' 

儘管如此,縮減的答案可能更快,通常會更好。

1

是的,剪切方式更好,並且匹配每個背面都比較容易。

我終於得到了使用每一行的開頭匹配:

sed -r 's/(([^_]*_){3}([^_]*)).*/\1/' oldFile > newFile 
2
sed -e 's/\([^_]*\)_\([^_]*\)_\([^_]*\)_\([^_]*\)_.*/\1_\2_\3_\4' infile > outfile 

匹配「任意數量的不是‘_’」,節約了什麼\(和\)之間的匹配,其次是'_'。做4次,然後匹配其餘部分的任何內容(被忽略)。用'_'分隔的每個匹配代替。

2

這裏的另一種可能性:

sed -E -e 's|^([^_]+(_[^_]+){3}).*$|\1|' 

其中-E,像GNU -r戰略經濟對話開啓的可讀性擴展正則表達式。

只因爲你可以在sed中做它,但並不意味着你應該。我喜歡爲此更好地剪切。

1

AWK喜歡的領域發揮:

awk 'BEGIN{FS=OFS="_"}{print $1,$2,$3,$4}' inputfile 

,或者更一般地說:

awk -v count=4 'BEGIN{FS="_"}{for(i=1;i<=count;i++){printf "%s%s",sep,$i;sep=FS};printf "\n"}'