grep 管道进入 sed,替换内联;但我想 sed 打印文件名和更改的行。是否可以?

gjt*_*ian 7 grep pipe sed

这是我的命令(故意中断):

grep FOO "/Users/gjtorikian/blah" -l | xargs sed -i '' '/FOO/{s/FOO/BAR/g; w /dev/stdout
}'
Run Code Online (Sandbox Code Playgroud)

在高层:grep用于blah目录中的FOO ;管道中的文件名(因为-l)到sed; sed执行内联替换 ( -i '') 并仅将更改的项打印到/dev/stdout

如果我要省略-l和管道,我会从grep

/Users/gjtorikian/blah/baz.cs:1:FOO
/Users/gjtorikian/blah/bar.js:1:FOO
Run Code Online (Sandbox Code Playgroud)

我想要的是sed执行内联替换,然后显示我替换的文件和术语;例如:

/Users/gjtorikian/blah/baz.cs:1:BAR
/Users/gjtorikian/blah/bar.js:1:BAR
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?如果重要,我宁愿只保留它grep/ sed。我必须做第二次grep以后sed

Gil*_*il' 4

一种可能性是将 的输出传递grep到单独的sed过滤器。

grep -l FOO "/Users/gjtorikian/blah/"* |
{ tee /dev/fd/3 |
  xargs sed -i -e '/FOO/{' -e 's/FOO/BAR/g' -e 'w /dev/stdout'
} 3>&1 | sed 's/:FOO$/:BAR/'
Run Code Online (Sandbox Code Playgroud)

当找到匹配项时,您可以sed打印行号(使用命令)并进行进一步的后处理。=

使用 awk 可能会更清楚。

for x in "/Users/gjtorikian/blah/"*; do
  awk '
    sub(/FOO/, "BAR") {found=1; print FILENAME ":" NR ":" "BAR" >"/dev/stderr"}
    1 {print}
    END {exit(!found)}
' "$x" >"$x.tmp" && mv "$x.tmp" "$x"
done
Run Code Online (Sandbox Code Playgroud)