如何报告“sed”就地更改

如何报告“sed”就地更改

当使用sed就地替换字符串时,有没有办法让它报告它所做的更改(而不依赖于新旧文件的差异)?

例如,如何更改命令行

find . -type f | xargs sed -i 's/abc/def/g'

这样我就可以看到即时所做的更改?

答案1

如果您的系统支持,您可以将sedsw标志与 , 一起/dev/stderr使用。例如,输入如下:/dev/tty/dev/fd/2file

foo first
second: missing
third: foo
none here

跑步

sed -i '/foo/{
s//bar/g
w /dev/stdout
}' file

输出:

bar first
third: bar

虽然file内容改为:

bar first
second: missing
third: bar
none here

所以在你的情况下,运行:

find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
s//bar/g
w /dev/fd/2
}' {} \;

将就地编辑文件并输出:

./文件1:
酒吧的东西
更多酒吧

./文件2:

./文件3:
酒吧第一
第三:酒吧

您还可以打印类似的内容,original line >>> modified line例如:

find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
h
s//bar/g
H
x
s/\n/ >>> /
w /dev/fd/2
x
}' {} \;

就地编辑文件并输出:

./文件1:
foo 的东西 >>> 酒吧的东西
更多 foo >>> 更多 bar

./文件2:

./文件3:
foo 首先 >>> bar 首先
第三:foo >>> 第三:bar

答案2

p您可以在第一遍中使用 rint 操作分两遍完成:

find . -type f | xargs sed --quiet 's/abc/def/gp'

where--quiet使 sed 不显示每一行,p后缀仅显示替换匹配的行。

这有 sed 不会显示的限制哪个文件正在被更改,这当然可以通过一些额外的复杂性来修复。

答案3

我认为这是不可能的,但解决方法可能是使用 perl 代替:

find . -type f -exec perl -i -pe 's/abc/def/ && print STDERR' {} +

这将打印改变的行到标准错误。例如:

$ cat foo
fooabcbarabc
blah blah
$ find . -type f -exec perl -i -pe 's/abc/def/ && print STDERR' {} +
foodefbarabc
$ cat foo
foodefbarabc
blah blah

您还可以使其稍微复杂一些,打印行号、文件名、原始行和更改的行:

$ find . -type f -exec perl -i -pe ' 
   $was=$_; chomp($was);
   s/abc/def/ && print STDERR "$ARGV($.): $was : $_"
   close ARGV if eof' {} +
./foo(1): fooabcbarabc : foodefbarabc

请注意每个文件之间close ARGV if eof需要$.重置的 。

将标志添加gs///运算符以替换每行中出现的所有内容,而不仅仅是第一行。

答案4

我喜欢 @terdon 解决方案 - perl 对此很有用。

这是我的调整版本:

  • 不会尝试更改没有匹配字符串的文件
  • 将备份更改的文件的之前版本(创建 .bak 版本)
  • 将列出每个文件/未更改的行,并显示该行的旧版本和新版本,缩进并位于下方,以便于阅读

代码

find /tmp/test -type f ! -name "*.bak" -exec grep -l '/opt/gridmon' {} \; | xargs -L1 perl -ni'.bak' -e'$old=$_; s/\/opt\/gridmon/~/g && print STDERR "$ARGV($.):\n\tOLD:$old\tNEW:$_"'

示例输出

/tmp/test/test4.cfg(13):
    OLD:    ENVFILE /opt/gridmon/server/etc/gridmonserver.cfg
    NEW:    ENVFILE ~/server/etc/gridmonserver.cfg
/tmp/test/test4.cfg(24):
    OLD:    ENVFILE /opt/gridmon/server/etc/gridmonserver.cfg
    NEW:    ENVFILE ~/server/etc/gridmonserver.cfg

相关内容