【问题标题】:I have an issue with a while read line bash script with sed command to delete lines, and following lines我对使用 sed 命令删除行和以下行的 while read line bash 脚本有疑问
【发布时间】:2015-04-30 03:49:25
【问题描述】:

我有一个 bash 脚本,我想用它从 SedTest.names 中读取行列表并删除该行和文件 SedTest.fasta 中的以下行。脚本看起来像

while read line; do
 sed "/${line}/{N;d}" SedTest.fasta 
done < "SedTest.names"

SedTest.fasta 看起来像

>seq1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>seq2
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
>seq3
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
>seq4
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
>seq5
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
>seq6
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
>seq7
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
>seq8
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
>seq9
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
>seq10
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ

而 SedTest.names 看起来像

>seq3
>seq5
>seq6

当我运行脚本并将输出直接输出到 test.out 时,test.out 看起来像

>seq1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>seq2
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
>seq4
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
>seq5
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
>seq6
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
>seq7
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
>seq8
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
>seq9
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
>seq10
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ

>seq1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>seq2
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
>seq3
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
>seq4
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
>seq6
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
>seq7
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
>seq8
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
>seq9
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
>seq10
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ

>seq1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>seq2
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
>seq3
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
>seq4
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
>seq5
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
>seq7
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
>seq8
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
>seq9
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
>seq10                     
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ

它已按要求删除了该行和下一行,但已分别为 SedTest.names 中的 3 行中的每一行编辑了 SedTest.fasta 中的数据。我需要通过删除所有 3 行及其以下行来修改一组输出数据,从而使 outfile 大小为 14 行。 我觉得这种方法非常接近,但我太厚了,不知道为什么它不起作用。非常感谢任何帮助!

【问题讨论】:

    标签: bash sed while-loop


    【解决方案1】:

    问题在于每个sed 命令都会为names 文件中的每一行处理整个文件。我更喜欢 awk 作为替代方案,因为它可以使用关联数组来保存来自不同文件的值并且只处理一次,例如:

    awk '
      FNR == NR { names[$1] = 1; next }
      { if ($1 in names) { getline; next } }
      { print }
    ' SedTest.names SedTest.fasta
    

    FNR == NR 块中,将名称保存到一个数组中,第二个比较是否存在,然后getline 读取下一行并跳过它。其余正常打印

    它产生:

    >seq1
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    >seq2
    BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
    >seq4
    DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
    >seq7
    GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    >seq8
    HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
    >seq9
    IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
    >seq10
    JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
    

    【讨论】:

    • 非常感谢 Birei。虽然 sed 选项现在可以工作,但它似乎不允许 stdout 重定向,因此 infile 被永久更改。我可以看到这个 awk 选项可能是一个更优雅的选项,假设您可以将输出定向到一个输出文件。
    • @DanielJ:操作系统完成了这项工作,在fasta 文件之后附加&gt; SedOutfile.txt
    【解决方案2】:

    您没有在 sed 中使用内联标志,也没有将文件保存到位。像这样使用你的循环:

    while read -r line; do
       sed -i.bak "/$line/{N;d;}" SedTest.fasta
    done < SedTest.names
    

    【讨论】:

    • 谢谢阿努巴瓦。我不得不对其进行一些修改以使其正常工作。它不喜欢单引号 '' 这似乎阻止它在 SedTest.fasta 中看到所需的行:sed: can't read />seq3/{N;d;}: No such file or directory sed: can' t 读取 />seq5/{N;d;}:没有这样的文件或目录 sed:无法读取 />seq6/{N;d;}:没有这样的文件或目录最终脚本看起来像(-r 似乎没有change things) 'while read line; do sed -i "/$line/{N;d;}" SedTest.fasta done
    • 就我所见,这个脚本会更改 infile 并且不允许重定向到 outfile(这不是太远!)。如果您以后需要原始版本,我建议您复制您的 infile。
    • 实际上-i.bak 是更安全的方法,因为它内联编辑文件,同时将原始文件保存在具有.bak 扩展名的文件中(请参阅更新的答案)
    • 我使用 -i.bak 选项发现的是它正在保存循环的最后一个版本的备份。所以原来的还是改了。你也一样吗?
    • 是的,我也一样。您还可以避免-i,并且只在循环外重定向一次输出,如下所示:done &lt; SedTest.names &gt; output
    猜你喜欢
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2010-09-25
    相关资源
    最近更新 更多