【问题标题】:Use SED to delete certain lines using an index with the line numbers to delete使用 SED 使用带有要删除的行号的索引来删除某些行
【发布时间】:2018-06-05 14:23:55
【问题描述】:

我得到一个大文件,称为 file.txt,它可能有 20000 行或更多。其中一些行必须从原始文件中删除,并且必须创建一个包含剩余行的新文件,例如 newfile.txt。要删除的行在另一个文件中,例如 index.txt。所以我是这样的:

文件.txt:

line1
line2
...
line19999
line20000

index.txt

11
56
79
...
19856

我一直在尝试使用 sed,试图让它使用索引中的数字来删除这些行,例如:

for i in ${index.txt[@]}
do
    sed -i.back '${i}d' file.txt>newfile.txt
done

但是,我收到一条错误消息 ${index.txt[@]}: bad substitution ,我不知道如何解决这个问题。

我也尝试过使用 gawk,但是代码有问题,我认为这与文件缩进制表符有关。如果有人可以提供帮助,我将不胜感激。

【问题讨论】:

    标签: linux bash awk sed grep


    【解决方案1】:

    不要不要循环调用 sed,那样会很慢。

    您可以将索引文件转换为 sed 脚本,然后对数据文件调用一次 sed:

    sed -i.bak "$(sed 's/$/d/' index.txt)" file.txt
    

    或者,正如@Hazzard17 指出的那样,忽略不只包含数字的行:

    script=$(sed -n '/^[[:blank:]]*[[:digit:]]\+[[:blank:]]*$/ s/$/d/p' index.txt)
    sed -i.bak "$script" file.txt
    

    一个演示:

    $ seq 20000 | sed 's/^/line/' > file.txt
    $ wc file.txt
     20000  20000 188894 file.txt
    $ seq 20000 | while read n; do [[ $RANDOM -le 5000 ]] && echo $n; done > index.txt
    $ wc index.txt
     3083  3083 16789 index.txt
    $ sed -i.bak "$(sed 's/$/d/' index.txt)" file.txt
    $ wc -l file.txt{,.bak}
     16917 file.txt
     20000 file.txt.bak
     36917 total
    

    要将文件读入数组,您可以:

    mapfile -t indices < index.txt
    for i in "${indices[@]}"; do ...; done
    

    或者只是遍历文件

    while IFS= read -r i; do ...; done < index.txt
    

    【讨论】:

    • 我建议将内部 sed 命令编辑为 sed -E '/[0-9]+/! d; s/$/d/' index.txt 以跳过任何空行,否则如果存在空行,则会从 file.txt 中删除所有行
    【解决方案2】:

    关注awk 可能会对您有所帮助。

    awk 'FNR==NR{a[$0];next} !(FNR in a)' index.txt file1.txt
    

    考虑到您的file1.txt 文件有我们需要从file1.txt 中删除的行号。如果您想在此处将输出保存到 Input_file(file1.txt) 中,还可以附加 &gt; temp_file &amp;&amp; mv temp_file file1.txt

    【讨论】:

      【解决方案3】:

      这是一个不修改你的 index.txt 并将结果输出到 newfile.txt 的解决方案:

      #replace new lines in the file with "d;"
      #After this, linenumbers will contain "11d;56d;79d;..."
      linenumbers=$(tr '\n' ';' < index.txt | sed 's/;/d;/g') 
      
      #write file.txt with specified line numbers removed to newfile.txt
      sed -e "$linenumbers" file.txt > newfile.txt
      

      【讨论】:

        猜你喜欢
        • 2011-05-14
        • 1970-01-01
        • 1970-01-01
        • 2013-11-20
        • 1970-01-01
        • 2018-08-16
        • 1970-01-01
        • 2013-05-01
        • 2013-04-08
        相关资源
        最近更新 更多