如何使用sed命令删除没有备份文件的行?
How to use sed command to delete lines without backup file?
我有 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 命令时,它也会创建备份文件。但是我在 root 中没有太多 space 。请尝试提供替代解决方案以从此文件中删除特定行而不增加服务器中的 space。
它不会创建真正的备份文件。 sed
是一个 stream 编辑器。当应用于带有选项 -i
的文件时,它将 stream 该文件通过 sed
进程,将输出写入 new 文件(一个临时文件),当一切都完成后,它会将新文件重命名为原来的名称。
(也有创建备份文件的选项,但是你没有给,所以我就不多说了。)
在您的情况下,您有一个非常大的文件并且不想创建任何副本,无论是临时的。为此你需要打开文件同时读取和写入,然后你的sed
进程可以覆盖原来的。在此之后,您必须在写作结束时对文件进行分类。运行
为了演示如何做到这一点,我们首先执行一个测试用例。
创建一个包含很多行的测试文件:
seq 0 999999 > x
现在,假设我们要删除所有包含数字 4
:
的行
grep -v 4 1<>x <x
这将打开文件作为 STDOUT (1) 进行读写,并作为 STDIN 进行读取。 grep
命令将读取所有行,并且只输出包含 4
(选项 -v
)的 而不是 的行。
这将有效地覆盖原始文件的开头。
你不会知道输出有多长,所以输出后会出现文件的原始内容:
…
999991
999992
999993
999995
999996
999997
999998
999999
537824
537825
537826
537827
537828
537829
…
之后您可以使用 Unix 工具 truncate
手动缩短您的文件。在实际场景中,您将很难找到合适的位置,因此计算写入的字节数(使用 wc
)是有意义的:
(不要忘记为这个测试重新创建原始 x
。)
(grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c
这将执行上述步骤并另外打印出写入终端的字节数,在本例中输出为 3653658
。现在使用 truncate
:
truncate -s 3653658 x
现在你得到了你想要的结果。
如果您想在脚本中执行此操作,我。 e.没有交互,你可以使用这个:
length=$((grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c)
truncate -s "$length" x
我不能保证这适用于您机器上 >2GB 或 >4GB 的文件;根据您的操作系统(32 位?)和安装的工具的版本,您可能 运行 遇到大文件问题。我会先对大文件进行测试(>4GB,因为这通常是很多事情的限制),然后祈祷并试一试 :)
一些注意事项你必须记住:
- 当然,没有人应该将日志条目附加到该日志文件 ,而 该过程是 运行ning。
- 此外,在进程 运行 期间的任何中止(电源故障、信号捕获等)都会使文件处于未定义状态。但是,在大多数情况下,在发生此类事故后再次运行重新执行命令会产生正确的输出;有些行可能会加倍,但此时损坏的行不应超过一行。
- 输出必须当然比输入小,否则写入会超过读取,破坏整个结果,使得应该存在的行会丢失(或 t运行cated 在开头)。
我有 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 命令时,它也会创建备份文件。但是我在 root 中没有太多 space 。请尝试提供替代解决方案以从此文件中删除特定行而不增加服务器中的 space。
它不会创建真正的备份文件。 sed
是一个 stream 编辑器。当应用于带有选项 -i
的文件时,它将 stream 该文件通过 sed
进程,将输出写入 new 文件(一个临时文件),当一切都完成后,它会将新文件重命名为原来的名称。
(也有创建备份文件的选项,但是你没有给,所以我就不多说了。)
在您的情况下,您有一个非常大的文件并且不想创建任何副本,无论是临时的。为此你需要打开文件同时读取和写入,然后你的sed
进程可以覆盖原来的。在此之后,您必须在写作结束时对文件进行分类。运行
为了演示如何做到这一点,我们首先执行一个测试用例。
创建一个包含很多行的测试文件:
seq 0 999999 > x
现在,假设我们要删除所有包含数字 4
:
grep -v 4 1<>x <x
这将打开文件作为 STDOUT (1) 进行读写,并作为 STDIN 进行读取。 grep
命令将读取所有行,并且只输出包含 4
(选项 -v
)的 而不是 的行。
这将有效地覆盖原始文件的开头。
你不会知道输出有多长,所以输出后会出现文件的原始内容:
…
999991
999992
999993
999995
999996
999997
999998
999999
537824
537825
537826
537827
537828
537829
…
之后您可以使用 Unix 工具 truncate
手动缩短您的文件。在实际场景中,您将很难找到合适的位置,因此计算写入的字节数(使用 wc
)是有意义的:
(不要忘记为这个测试重新创建原始 x
。)
(grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c
这将执行上述步骤并另外打印出写入终端的字节数,在本例中输出为 3653658
。现在使用 truncate
:
truncate -s 3653658 x
现在你得到了你想要的结果。
如果您想在脚本中执行此操作,我。 e.没有交互,你可以使用这个:
length=$((grep -v 4 <x | tee /dev/stderr 1<>x) |& wc -c)
truncate -s "$length" x
我不能保证这适用于您机器上 >2GB 或 >4GB 的文件;根据您的操作系统(32 位?)和安装的工具的版本,您可能 运行 遇到大文件问题。我会先对大文件进行测试(>4GB,因为这通常是很多事情的限制),然后祈祷并试一试 :)
一些注意事项你必须记住:
- 当然,没有人应该将日志条目附加到该日志文件 ,而 该过程是 运行ning。
- 此外,在进程 运行 期间的任何中止(电源故障、信号捕获等)都会使文件处于未定义状态。但是,在大多数情况下,在发生此类事故后再次运行重新执行命令会产生正确的输出;有些行可能会加倍,但此时损坏的行不应超过一行。
- 输出必须当然比输入小,否则写入会超过读取,破坏整个结果,使得应该存在的行会丢失(或 t运行cated 在开头)。