当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何使用bash/sed脚本删除文本文件的第一行?》经验,为你挑选了10个好方法。

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

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

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



1> Aaron Digull..:

试试GNU尾巴:

tail -n +2 "$FILE"

-n x:只需打印最后x一行.tail -n 5会给你输入的最后5行.该+标志那种反转的争论,使tail打印任何东西,但第一x-1线.tail -n +1将打印整个文件,tail -n +2除第一行外的所有内容等.

GNU tail要快得多sed.tail也可以在BSD上使用,并且-n +2两个工具的标志是一致的.查看FreeBSD或OS X手册页了解更多信息.

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

注意:您可能很想使用

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

但这会给你一个空文件.原因是重定向(>)发生在tailshell调用之前:

    Shell截断文件 $FILE

    Shell为其创建了一个新流程 tail

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

    tail 从现在空的读取 $FILE

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

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

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


@Eddie:user869097表示当*single*行为15Mb或更多时,它不起作用.只要行更短,`tail`将适用于任何文件大小.
它不适用于15Mb或更多的行
@Dreampuf - 来自手册页:` - n N表示输出最后N行,而不是最后10行; 或使用+ N输出以Nth`开头的行
我打算同意@JonaChristopherSahnwaldt - 尾巴比sed变种慢很多,比一个数量级要慢得多.我正在一个500,000K行的文件上测试它(每行不超过50个字符).然而,我意识到我使用的是FreeBSD版本的tail(默认情况下附带OS X).当我切换到GNU尾部时,尾部调用比sed调用快10倍(以及GNU sed调用).如果你正在使用GNU,那么AaronDigulla在这里是正确的.
你能解释一下这些论点吗?
@user:有趣的一点.你从哪里得到这个号码?
根据这个http://ss64.com/bash/tail.html,当使用BSD'tail'和`-r`选项时,典型的缓冲区默认为32k.也许系统中某处有缓冲区设置?或者`-n`是一个32位有符号数?
哎呀.谢谢你纠正我.WO,15mb线..我甚至无法想象这样的情况.
@Dreampuf:`sed`有一个当前行的内部缓冲区,而`tail`可以通过记住N个最后一个换行符的偏移来消失(注意我实际上没有查看源代码).

2> 小智..:

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

sed -i '1d' filename


这每次都有效,真的应该是最好的答案!
Just to remember, Mac requires a suffix to be provided when using sed with in-place edits. So run the above with -i.bak
这个版本比`tail -n + 2`更可读,更通用.不确定为什么它不是最佳答案.
只需注意-要删除几行,请使用`sed -i'1,2d'filename'

3> Nasri Najib..:

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

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


有趣的人口统计

4> paxdiablo..:

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

但是你的问题与许多其他问题一样,因为它预先设定了解决方案.如果你要详细告诉我们什么你想要做而不是如何,我们也许能够提出更好的选择.

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

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

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

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

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



5> alexis..:

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

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

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



6> Robert Gambl..:

正如Pax所说,你可能不会比这更快.原因是几乎没有文件系统支持从文件开头截断,因此这将是一个O(n)操作,其中n是文件的大小.你可以做,虽然速度是覆盖具有相同的字节数(也许用空格或注释),这可能会为您取决于正是你正在尝试做的工作第一线(那是什么来着?).



7> agc..:

spongeUTIL避免了杂耍一个临时文件的需要:

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



8> Mark Reed..:

如果要修改到位的文件,你总是可以使用原始ed的,而不是它的小号 treaming继任者sed

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

ed命令是原始的UNIX文本编辑器,甚至没有全屏终端,而图形工作站则少得多。在ex编辑器中,最有名的你使用的是什么类型时,在结肠中的提示vi,是一个的趋向版本ed,所以很多相同的命令工作。尽管ed本意是要交互使用,但也可以通过向其发送一串命令来以批处理方式使用它,这就是该解决方案的作用。

序列<<<$'1d\nwq\n'利用了bash的支持,这里串(<<<)和POSIX引号($'... '),以饲料投入到ed由两行命令:1d,其中d eletes行1,然后wq,这W¯¯仪式的文件重新出磁盘,然后q UITS编辑会话。



9> 小智..:

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

cat filename | sed 1d > filename_without_first_line

在命令行上;或要永久删除文件的第一行,请使用sed的就地模式和以下-i标志:

sed -i 1d 



10> Hongbo Liu..:

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

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

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

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有