Linux 如何使用sed命令在没有备份文件的情况下删除行?

Linux 如何使用sed命令在没有备份文件的情况下删除行?,linux,file,vim,sed,redhat,Linux,File,Vim,Sed,Redhat,我有一个130GB大小的大文件 # ls -lrth -rw-------. 1 root root 129G Apr 20 04:25 syslog.log 所以我需要通过删除以“Nov 2”开头的行来减小文件大小,所以我给出了以下命令 sed -i '/Nov 2/d' syslog.log 所以我也不能使用VIM编辑器编辑文件 当我触发SED命令时,它也会创建备份文件。但是我在根上没有太多的空间。请尝试提供替代解决方案,从该文件中删除特定行,而不增加服务器中的空间。它不会创建真正的备

我有一个130GB大小的大文件

# ls -lrth
-rw-------. 1 root root 129G Apr 20 04:25 syslog.log
所以我需要通过删除以“Nov 2”开头的行来减小文件大小,所以我给出了以下命令

sed -i '/Nov  2/d' syslog.log
所以我也不能使用VIM编辑器编辑文件


当我触发SED命令时,它也会创建备份文件。但是我在根上没有太多的空间。请尝试提供替代解决方案,从该文件中删除特定行,而不增加服务器中的空间。

它不会创建真正的备份文件
sed
是一个流编辑器。当应用到带有选项
-i
的文件时,它将通过
sed
流程流式传输该文件,将输出写入新文件(临时文件),完成所有操作后,它将将新文件重命名为原始名称

(也有创建备份文件的选项,但您没有提供这些选项,因此我不再进一步提及。)

在您的情况下,您有一个非常大的文件,不想创建任何副本,无论是多么临时。为此,您需要同时打开文件进行读写,然后您的
sed
过程可以覆盖原始文件。在此之后,您必须在写入结束时截断文件

为了演示如何做到这一点,我们首先执行一个测试用例

创建包含大量行的测试文件:

seq 0 999999 > x
现在,假设我们要删除包含数字
4
的所有行:

grep -v 4 1<>x <x
之后,您可以使用Unix工具
truncate
手动缩短文件。在实际场景中,您将很难找到正确的位置,因此计算写入的字节数(使用
wc
):

(不要忘记为本测试重新创建原始的
x

现在你得到了你想要的结果

如果你想在脚本中这样做,我。E在没有交互的情况下,您可以使用:

length=$((grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c)
truncate -s "$length" x
length=$((计算机上的grep-v4 2GB或>4GB;取决于您的操作系统(32位?)和所安装工具的版本,您可能会遇到大文件问题。我会先对大文件执行测试(>4GB,因为这通常是很多事情的限制),然后交叉手指并尝试一下:)

一些注意事项您必须记住:

  • 当然,当过程运行时,没有人应该将日志条目附加到该日志文件中
  • 此外,进程运行期间的任何中止(电源故障、信号捕获等)都会使文件处于未定义状态。但在这种情况下,再次运行命令在大多数情况下都会产生正确的输出;某些行可能会加倍,但损坏的行数不应超过一行
  • 当然,输出必须小于输入,否则写入将超过读取,破坏整个结果,因此应该存在的行将丢失(或在开始时被截断)

它为什么还要创建一个备份文件?它的名字是什么?如果你说
sed-i'
?你肯定是戴着红帽还是在OSX?同意,我想不出任何shell方法来实现不复制的把戏。鉴于Unix文件系统的语义,我很难想出任何可以避免部分复制的方法。@msw:谢谢你的建议在上,我将尝试要求存储团队提供空间。++;在两个切题上:
seq 1000000>x
是创建测试文件的一个更快的选择。调用
truncate
一个“shell实用程序”有点混乱(它是一个与shell本身无关的CLI)@mklement0谢谢你的建议,我在答案中采纳了你的意见(我认为术语“Unix工具”比“shell实用工具”更合适)。@Alfe:太好了……它可以工作了,我已经将文件大小从129GB减少到107GB。感谢你及时的帮助。。。。。
(grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c
truncate -s 3653658 x
length=$((grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c)
truncate -s "$length" x