从以特定字符开头的行中删除子字符串



我正在尝试更改以>开始的行中的长名称,以便我只保留部分直到Stage_V_sporulation_protein...:

>tr_A0A024P1W8_A0A024P1W8_9BACI_Stage_V_sporulation_protein_AE_OS=Halobacillus_karajensis_OX=195088_GN=BN983_00096_PE=4_SV=1
MTFLWAFLVGGGICVIGQILLDVFKLTPAHVMSSFVVAGAVLDAFDLYDNLIRFAGGGATVPITSFGHSLLHGAMEQADEHGVIGVAIGIFELTSAGIASAILFGFIVAVIFKPKG
>tr_A0A060LWV2_A0A060LWV2_9BACI_SpoIVAD_sporulation_protein_AEB_OS=Alkalihalobacillus_lehensis_G1_OX=1246626_GN=BleG1_2089_PE=4_SV=1
MIFLWAFLVGGVICVIGQLLMDVVKLTPAHTMSTLVVSGAVLAGFGLYEPLVDFAGAGATVPITSFGNSLVQGAMEEANQVGLIGIITGIFEITSAGISAAIIFGFIAALIFKPKG

我正在做一个循环:

cat file.txt | while read line; do 
if [[ $line = >* ]] ; then
cut -d_ -f1-4 $line; 
fi; 
done

但是在地址文件中,而不是在文件中的行(我得到cut: >>tr_A0A024P1W8_A0A024P1W8_9BACI_Stage_V_sporulation_protein_AE_OS=Halobacillus_karajensis_OX=195088_GN=BN983_00096_PE=4_SV=1: No such file or directory)。

我想要的输出是:

>tr_A0A024P1W8_A0A024P1W8_9BACI        
MTFLWAFLVGGGICVIGQILLDVFKLTPAHVMSSFVVAGAVLDAFDLYDNLIRFAGGGATVPITSFGHSLLHGAMEQADEHGVIGVAIGIFELTSAGIASAILFGFIVAVIFKPKG
>tr_A0A060LWV2_A0A060LWV2_9BACI        
MIFLWAFLVGGVICVIGQLLMDVVKLTPAHTMSTLVVSGAVLAGFGLYEPLVDFAGAGATVPITSFGNSLVQGAMEEANQVGLIGIITGIFEITSAGISAAIIFGFIAALIFKPKG

如何更改实际行?

在问题的当前状态下,似乎最容易做到的是:

awk '/^>/ {print $1,$2,$3,$4; next}1' FS=_ OFS=_ file.txt

行开头匹配>的行只打印前四个字段,用_(OFS的值)分隔。不匹配的行将原样打印。

使用sed:

sed -E '/^>/s/(.*)_Stage_V_sporulation_protein/1/' file

sed的一行代码是:

sed '/^>/s/^(([^_]*_){3}[^_]*).*/1/' file

使用下面的Perl一行代码处理FASTA文件中的头文件:

perl -lpe 'if ( m{^>} ) { @f = split m{_}, $_; splice @f, 4; $_ = join "_", @f; }' file.txt > out.txt

Perl单行程序使用这些命令行标志:
-e:告诉Perl查找内联代码,而不是在文件中查找。
-p:每次循环输入一行,默认赋值给$_。在每次循环迭代后添加print $_
-l:在执行内联代码之前去掉输入行分隔符(*NIX默认为"n"),并在打印时附加。

一行代码使用split将下划线上的输入字符串拆分为数组@f.
然后使用splice从数组中删除除前4个元素外的所有元素。
最后,join用下划线连接这些元素。
以上所有内容都被包装在if ( m{^>} ) { ... }中,以便将昂贵的字符串操作限制在FASTA头(以>开头的行)。

参见:
perldoc perlrun:如何执行Perl解释器:命令行切换

最新更新