删除以特殊字符开头的整行,第一个单词除外

删除以特殊字符开头的整行,第一个单词除外

我最近才开始使用 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*

变成这样:

>YAL001C
MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*

答案1

我在这里提出四个解决方案,两个使用sed,一个使用awk,一个使用perl。首先:

$ sed -r 's/^(>[^ ]+) .*/\1/' inputfile

在您的示例输入上,这将产生输出:

>YAL001C
LTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*

代码使用了 sed 的替代命令s。替代命令的形式为s/old/new/。在本例中,“旧”部分由以下部分组成:

  • ^

    这是 sed 中表示行开头的意思。

  • (>[^ ]+)

    这是指由尖括号和一个或多个非空白字符组成的一组字符。由于这是在括号中,因此我们稍后可以将其称为\1

  • .*

    指的是空格后跟任意数量的任意字符。

当替换命令完成后,任何这样的行的全部内容都将被替换为紧随>其后的非空白字符。

任何不以该组合开头的行都将不加改变地发送到输出。

替代解决方案

在评论中,steeldriver 建议了一种替代方法:

sed '/^>/ s/\s.*//'

在这个解决方案中,替换命令前面有一个修饰符/^>/,它限制替换命令只能对以 开头的行进行操作>。知道该行以尖括号开头,那么只需要删除第一个空格以及第一个空格后面的所有内容。这就是命令的作用s/\s.*//

所有其他线路均按原样通过。

替代解决方案使用awk

awk '/^>/ {print $1;next} 1' inputfile

awk脚本由两个表达式组成:

  • /^>/ {print $1;next}

    awk支持与 相同的修饰符样式sed。因此,初始表达式限制此命令仅对以 开头的行进行操作>。对于这些行,将打印第一个字段。 next指示awk跳至下一行并重新开始。

  • 1

    1awk打印整行的神秘简写。此命令仅next在未执行前一个表达式中的命令的行上执行,这意味着awk仅当行不以 开头时才会到达此命令>

替代解决方案使用perl

steeldriver 还建议:

perl -anle 'print $F[0] if /^>/ || $_'

四个选项含义如下:

  • -n告诉perl隐式循环输入行

  • -a告诉 perl 启用自动分割,创建@F数组

  • -l启用自动行结束处理

  • -e告诉它运行后面的命令,从而无需 perl 脚本文件。

perl 命令本身相当易读:

print $F[0] if /^>/ || $_

如果行以 开头,则此命令打印第一个字段>。否则,它将打印整行。

相关内容