如何对文件进行就地修改?


10

对文件的“原位”修改(例如,通过sed -iperl -i表示)是什么?
我的问题是有关此就地修改是如何完成的。复制的文件是否在副本中完成修改,然后替换原始文件?还是以某种方式修改了原始文件?


请查看backreference.org/2011/01/29/in-place-editing-of-files,以获取有关此主题的详细说明。
scy 2014年

因此,如何使用ex或来完成vi
通配符

@Wildcard-每个人都有一个完整的系统。ex维护一个邮件文件dead.mail通常类似于〜you 或其他内容,以及另一个靠近假脱机程序的位置)。检查规范-每个规范都定义了很长的状态... ex在大多数情况下,具有自己的二进制格式(请查看您的-rescue文件),该规范用于将单独的临时缓冲区文件(可能多达六个)预置零。所以这些复制输入块到编辑缓冲区和同步写入每次更改的偏移量中:!written
mikeserv '19

Answers:


18

sed 创建一个临时文件,将输出写入该文件,然后在原始文件的顶部重命名该临时文件。

您可以使用观看发生的情况strace

$ strace -e trace=file sed -i -e '' a
execve("/usr/bin/sed", ["sed", "-i", "-e", "", "a"], [/* 34 vars */]) = 0
<...trimmed...>
open("a", O_RDONLY)                     = 3
open("./sedxvhRY8", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("./sedxvhRY8", "a")              = 0
+++ exited with 0 +++

这会记录所有文件操作sed:创建一个新文件(安全地使用O_CREAT|O_EXCL),将数据写入其中,然后将其移回到我的原始文件上方a

sed -i接受用于备份的后缀,在这种情况下,它将后缀先移开(而不是在顶部重命名)。在大多数BSD中,该参数是必需sed的。在这种情况下,有时会在目录中根本没有名称正确的文件。

perl 在最新版本中,将打开输入文件,然后将其删除并创建一个具有相同名称的新文件:

open("a", O_RDONLY)               = 3
unlink("a")                       = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4

当您删除(unlink)已打开的文件时,只要保持打开状态,就可以保留对该文件的访问权限,这样它就可以继续从删除的文件中读取数据。这样,可以perl直接写入输出文件,而不是临时文件:不会创建其他文件,但是,如果您在此过程中读取文件,则将获得部分内容,这与sed的方法不同。还有很短的时间,没有名称正确的文件,它是在流程的开始而不是结尾(如所示sed -i .bak)。


双方sedperl会:

  • 用普通文件替换符号链接。
  • 断开硬链接。
  • 如果可能,保留组的所有权。
  • 如果文件setgid属于您不在的组,并且不是root用户,则使用默认组(如果该目录包含位,则使用父目录的组)创建文件。
  • 如果您是root用户,则保留文件所有权。
  • 保留基本权限。
  • 如果结果组与其开始的组相同,保留setuidsetgrp位。
  • 保留粘性位。
  • 保留xattrs。

sed 将:

  • 保留ACL (在Linux上;我不了解其他 ACL

perl 将:

  • 保留ACL。

在具有GNU的Linux sed和带有(从FreeBSD派生的)Mac OS X的Linux上,以上情况是正确的sed


3

除了@Homer的答案,还来自perldoc perlrun

指定由“ <>”构造处理的文件将被就地编辑。它通过重命名输入文件,使用原始名称打开输出文件并选择该输出文件作为print()语句的默认值来做到这一点。扩展名(如果提供)用于遵循以下规则修改旧文件的名称以制作备份副本:

如果没有提供扩展名,则不会进行备份,并且当前文件将被覆盖。

如果扩展名不包含*,则将扩展名作为后缀附加到当前文件名的末尾。如果扩展名确实包含一个或多个*字符,则每个*将替换为当前文件名。

请记住,没有保留软链接或硬链接:

请注意,由于-i在创建具有相同名称的新文件之前会重命名或删除原始文件,因此将不会保留UNIX样式的软链接和硬链接。

最后,当命令行上未提供任何文件时,-i开关不会阻止执行。在这种情况下,不进行备份(当然无法确定原始文件),并且处理可能从STDIN进行到STDOUT。

这也解释了为什么必须使用-iwith -p选项,或者print如果要使用以下命令进行原位编辑,则必须使用显式语句perl

# Opps, file will be truncated, becomes empty
$ perl -i.bak -ne 's/123/qwe/' file

# Right way
$ perl -i.bak -ne 's/123/qwe/;print' file

# Or
$ perl -i.bak -pe 's/123/qwe/' file
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.