在unix命令行中删除文件的前N行

Mit*_*ops 9 bash awk sed command-line-interface

我正在尝试从非常非常大的文件中删除前37行.我开始尝试使用sed和awk,但它们似乎需要将数据复制到新文件中.我正在寻找一个"删除就地线"的方法,不像sed -i是不制作任何类型的副本,而只是从现有文件中删除行.

这就是我所做的......

awk 'NR > 37' file.xml > 'f2.xml'
sed -i '1,37d' file.xml
Run Code Online (Sandbox Code Playgroud)

这两个似乎都做了完整的副本.是否还有其他简单的CLI可以在没有完整文档遍历的情况下快速完成此操作?

Ed *_*ton 10

使用UNIX实用程序进行现场编辑没有简单的方法,但这里有一个就地文件修改解决方案,您可以修改它以便为您工作(由Robert Bonomi提供,https: //groups.google.com/forum/# ! topic/comp.unix.shell/5PRRZIP0v64):

bytes=$(head -37 "$file" |wc -c)
dd if="$file" bs="$bytes" skip=1 conv=notrunc of="$file"
Run Code Online (Sandbox Code Playgroud)

最终文件应该是$count比原始文件小的字节(因为目标是$count从头开始删除字节),所以要完成我们必须删除最后的$count字节.在像GNU这样的GNU系统上,这可以通过以下方式实现:

truncate -s "-$bytes" "$file"
Run Code Online (Sandbox Code Playgroud)

有关其他建议和信息,请参阅我引用的Google网上论坛帖子.

  • 在linux上,你需要在`dd`中使用`conv = notrunc`,否则命令失败.`+ 1`. (3认同)
  • 这在Google网上论坛帖子中有所提及,但从未拼写过:完成后你必须从文件末尾修剪最后的`$ count`字节.我编辑了你的答案以反映这一点,以便未来的读者有一个完整的解决方案. (2认同)

tha*_*guy 6

Unix文件语义不允许截断文件的前部.

所有解决方案都将基于:

  1. 文件读入内存,然后写回(ed,ex,其他编辑器).如果您的文件<1GB或者有足够的RAM,这应该没问题.
  2. 编写第二个副本并可选择替换原始(sed -i,awk/ tail > foo).只要您有足够的可用磁盘空间用于副本,并且不介意等待,这样就可以了.

如果文件太大而无法使用这些文件,您可以根据文件的读取情况来解决问题.

也许您的读者会跳过评论或空白行?如果是这样,您可以制作读者忽略的消息,确保它与文件中的第37行具有相同的字节数,并覆盖文件的开头dd if=yourdata of=file conv=notrunc.

  • 嗯,没有想到这一点.如果我在bunzip2-ing文件时这样做 - 你说我会把解压缩到awk和那个outfile吗?那么,这就像`bunzip2 filename.xml.bz2 | awk'NR> 37'filename.xml` (2认同)

gni*_*urf 5

是标准编辑器:

ed -s file <<< $'1,37d\nwq'
Run Code Online (Sandbox Code Playgroud)

  • +1 这很快。包含 1m 个条目的文件 - `$ time ed -s ff &lt;&lt;&lt; $'1,37d\nwq' real 0m0.251s user 0m0.219s sys 0m0.032s $ time sed -i '1,37d' ff real 0m1.415s用户 0m0.399s 系统 0m1.016s` (2认同)