2010-06-24 161 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"}'