首页 文章

如何使用bash / sed脚本删除文本文件的第一行?

提问于
浏览
432

我需要使用bash脚本从一个巨大的文本文件中重复删除第一行 .

现在我正在使用 sed -i -e "1d" $FILE - 但删除大约需要一分钟 .

有没有更有效的方法来实现这一目标?

15 回答

  • 16

    用csplit怎么样?

    man csplit
    csplit -k file 1 '{1}'
    
  • 65

    由于听起来我无法加速删除,我认为一个好的方法可能是批量处理文件,如下所示:

    While file1 not empty
      file2 = head -n1000 file1
      process file2
      sed -i -e "1000d" file1
    end
    

    这样做的缺点是,如果程序在中间被杀死(或者如果那里有一些不好的sql - 导致“进程”部分死亡或锁定),则会有跳过或被处理两次的行 .

    (file1包含sql代码行)

  • 106

    如果要修改文件,可以始终使用原始 ed 而不是 s treaming successor sed

    ed "$FILE" <<<$'1d\nwq\n'
    
  • 3

    您可以使用-i更新文件,而无需使用“>”运算符 . 以下命令将从文件中删除第一行并将其保存到文件中 .

    sed -i '1d' filename
    
  • 8

    不,这就像你要获得的那样高效 . 你可以编写一个C程序,它可以更快地完成工作(减少启动时间和处理参数)但它可能会趋向于与文件变大的sed相同的速度(并且我认为如果需要一分钟,它们会很大) .

    但是你的问题与许多其他问题一样,因为它预先设定了解决方案 . 如果你要详细告诉我们 what 你试图做的事情,而不是 how ,我们可能会建议一个更好的选择 .

    例如,如果这是某个其他程序B处理的文件A,则一种解决方案是不剥离第一行,而是修改程序B以不同方式处理它 .

    假设所有程序都附加到此文件A,程序B当前在删除它之前读取并处理第一行 .

    您可以重新设计程序B,以便它不会尝试删除第一行但是在文件A中保持一个持久的(可能是基于文件的)偏移量,以便下次运行时可以寻找该偏移量,进程那里的线,并更新偏移量 .

    然后,在安静的时间(午夜?),它可以对文件A进行特殊处理,以删除当前处理的所有行,并将偏移量设置回0 .

    程序打开和查找文件而不是打开和重写肯定会更快 . 当然,本讨论假定您可以控制程序B.我不知道是否是这种情况,但如果您提供进一步的信息,可能还有其他可能的解决方案 .

  • -1

    应显示除第一行以外的行:

    cat textfile.txt | tail -n +2
    
  • 837

    你可以轻松地做到这一点:

    cat filename | sed 1d > filename_without_first_line
    

    在命令行上;或者永久删除文件的第一行,使用带有 -i 标志的sed就地模式:

    sed -i 1d <filename>
    
  • 0

    可以使用vim来做到这一点:

    vim -u NONE +'1d' +'wq!' /tmp/test.txt
    

    这应该更快,因为vim在处理时不会读取整个文件 .

  • 2

    试试GNU tail

    tail -n +2 "$FILE"
    

    -n x :只需打印最后的 x 行 . tail -n 5 将为您提供输入的最后5行 . + 符号反转参数并使 tail 打印除第一个 x-1 行以外的任何内容 . tail -n +1 将打印整个文件, tail -n +2 除第一行外的所有内容等 .

    GNU tailsed 快得多 . tail 也可用于BSD, -n +2 标志在两个工具中都是一致的 . 查看FreeBSDOS X手册页以获取更多信息 .

    但是,BSD版本可能比 sed 慢得多 . 我想知道他们是如何做到的; tail 应该只是逐行读取文件,而 sed 执行相当复杂的操作,包括解释脚本,应用正则表达式等 .

    注意:您可能很想使用

    # THIS WILL GIVE YOU AN EMPTY FILE!
    tail -n +2 "$FILE" > "$FILE"
    

    但这会给你一个 empty file . 原因是重定向( > )发生在shell调用 tail 之前:

    • Shell截断文件 $FILE

    • Shell为 tail 创建一个新进程

    • Shell将 tail 进程的stdout重定向到 $FILE

    • tail 从现在空的 $FILE 读取

    如果要删除文件中的第一行,则应使用:

    tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
    

    && 将确保在出现问题时不会覆盖该文件 .

  • 5

    can 编辑文件:只需使用perl的 -i 标志,如下所示:

    perl -ni -e 'print unless $. == 1' filename.txt
    

    这会使第一行消失,正如你所问的那样 . Perl需要读取和复制整个文件,但它会安排输出以原始文件的名称保存 .

  • 9

    对于那些使用非GNU的SunOS的人,以下代码将有所帮助:

    sed '1d' test.dat > tmp.dat
    
  • -1

    如果你想要做的是在失败后恢复,你可以 Build 一个具有你迄今为止所做的事情的文件 .

    if [[ -f $tmpf ]] ; then
        rm -f $tmpf
    fi
    cat $srcf |
        while read line ; do
            # process line
            echo "$line" >> $tmpf
        done
    
  • -1

    正如Pax所说,你可能不会比这更快 . 原因是那里几乎没有支持从文件开头截断的文件系统,所以这将是一个O( n )操作,其中 n 是文件的大小 . 你可以做得更快但是用相同的字节数(可能带空格或注释)覆盖第一行,这可能对你有用,具体取决于你想要做什么(顺便说一句是什么?) .

  • 2

    会在N-1行上使用tail并将其导入文件,然后删除旧文件,并将新文件重命名为旧名称吗?

    如果我以编程方式执行此操作,我会读取文件,并在读取每一行后记住文件偏移量,因此我可以回到该位置以读取文件中少一行 .

  • 3

    sponge util避免了玩杂耍临时文件的需要:

    tail -n +2 "$FILE" | sponge "$FILE"
    

相关问题