我最近开始使用 linux 并且我几乎完全忘记了 sed 命令。我需要编辑一个包含一堆以公共字符“>”开头的长行的文件,并删除该行的其余部分,只保留第一个单词,但不要使用 sed 命令触及任何不以“>”开头的行。
换句话说,我需要转这个(为了演示目的,只是第一个条目的一部分):
>YAL001C TFC3 SGDID:S000000001, Chr I from 151006-147594,151166-151097, Genome Release 64-1-1, reverse complement, Verified ORF, "Largest of six subunits of the RNA polymerase III transcription initiation factor complex (TFIIIC); part of the TauB domain of TFIIIC that binds DNA at the BoxB promoter sites of tRNA and similar genes; cooperates with Tfc6p in DNA binding"
MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*
Run Code Online (Sandbox Code Playgroud)
进入这个:
>YAL001C
MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*
Run Code Online (Sandbox Code Playgroud)
我在这里介绍了四种解决方案,两种使用sed,一种使用awk,一种使用perl。开始:
$ sed -r 's/^(>[^ ]+) .*/\1/' inputfile
Run Code Online (Sandbox Code Playgroud)
在您的示例输入上,这会产生输出:
>YAL001C
LTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*
Run Code Online (Sandbox Code Playgroud)
该代码使用 sed 的替代命令s。替代命令的形式为s/old/new/。在这种情况下,“旧”部分由以下部分组成:
^
这是一行开始的 sed-speak。
(>[^ ]+)
这是指由尖括号后跟一个或多个非空白字符组成的一组字符。因为这是在括号中,我们稍后可以将其称为\1.
.*
这是指一个空格后跟任意数量的任意字符。
当替换命令完成时,任何这样的一行的整个都被替换为>紧随其后的和非空白字符。
任何不以该组合开头的行都将不变地发送到输出。
在评论中,steeldriver 提出了另一种方法:
sed '/^>/ s/\s.*//'
Run Code Online (Sandbox Code Playgroud)
在此解决方案中,替换命令前面是修饰符/^>/,该修饰符限制替换命令仅在以 开头的行上运行>。知道该行以尖括号开头,那么只需删除第一个空格和第一个空格后面的所有内容。这就是命令的s/\s.*//作用。
所有其他线路不变地通过。
awkawk '/^>/ {print $1;next} 1' inputfile
Run Code Online (Sandbox Code Playgroud)
该awk脚本由两个表达式组成:
/^>/ {print $1;next}
awk支持与sed. 因此,初始表达式将此命令限制为仅对以 开头的行进行操作>。对于这些行,打印第一个字段。 next告诉awk跳到下一行并重新开始。
1
1is 是awk打印整行的神秘简写。这仅在next未执行前面表达式中的awk命令的行上执行,这意味着仅当该行不以>.
perlSteeldriver 还建议:
perl -anle 'print $F[0] if /^>/ || $_'
Run Code Online (Sandbox Code Playgroud)
这四个选项的含义如下:
-n告诉perl隐式循环输入行
-a告诉 perl 打开自动拆分,创建@F数组
-l 启用自动行尾处理
-e 告诉它运行下面的命令,消除对 perl 脚本文件的需要。
perl 命令本身是相当可读的:
print $F[0] if /^>/ || $_
Run Code Online (Sandbox Code Playgroud)
如果该行以>. 否则,它将打印整行。