在bash上显示查找/替换多个文档的结果
我喜欢使用以下命令在bash中跨多个文件查找/替换:在bash上显示查找/替换多个文档的结果,bash,shell,replace,find,xargs,sed,Bash,Shell,Replace,Find,Xargs,Sed,我喜欢使用以下命令在bash中跨多个文件查找/替换: find -wholename "*.txt" -print | xargs sed -i 's/foo/bar/g' 但是,上面的命令以静默方式处理所有内容,有时我希望上面的命令打印它所做的所有更改,以便再次检查我是否正确地完成了所有操作。我可以知道应该如何改进上述命令以允许它转储此类信息吗?我在xargs命令中尝试了-v参数,但它给了我无效选项错误。您可以执行以下操作: find -wholename "*.txt"
find -wholename "*.txt" -print | xargs sed -i 's/foo/bar/g'
但是,上面的命令以静默方式处理所有内容,有时我希望上面的命令打印它所做的所有更改,以便再次检查我是否正确地完成了所有操作。我可以知道应该如何改进上述命令以允许它转储此类信息吗?我在
xargs
命令中尝试了-v
参数,但它给了我无效选项
错误。您可以执行以下操作:
find -wholename "*.txt" | xargs sed -n '/foo/p;s/foo/bar/gp'
这样做的目的是打印要替换的行,并在下一行中打印替换
您可以使用awk
并获取文件名:
find -wholename "*.txt" | xargs awk '/foo/{print FILENAME; gsub(/foo/,"bar");print}'
要打印整个文件,请删除print
并添加1
find -wholename "*.txt" | xargs awk '/foo/{print FILENAME; gsub(/foo/,"bar")}1'
Regex必须根据您的要求进行修改,文件中的更改仅在gawk版本4.1中可用
测试:
$head文件*
==>file1 file2您可以执行以下操作:
find -wholename "*.txt" | xargs sed -n '/foo/p;s/foo/bar/gp'
这样做的目的是打印要替换的行,并在下一行中打印替换
您可以使用awk
并获取文件名:
find -wholename "*.txt" | xargs awk '/foo/{print FILENAME; gsub(/foo/,"bar");print}'
要打印整个文件,请删除print
并添加1
find -wholename "*.txt" | xargs awk '/foo/{print FILENAME; gsub(/foo/,"bar")}1'
Regex必须根据您的要求进行修改,文件中的更改仅在gawk版本4.1中可用
测试:
$head文件*
==>file1 file2为了查看差异,您可以将sed
的输出重定向到每个输入文件的新文件,并将其与原始文件进行比较
for i in `find -wholename "*.txt"`; do
sed 's/foo/bar/g' ${i} > ${i}.new;
diff -u ${i} ${i}.new;
done
如果更改看起来正常,请将新文件移到其原始名称
for i in `find -wholename "*.new"` ; do
mv ${i} ${i/.new};
done
为了查看差异,您可以将sed
的输出重定向到每个输入文件的新文件,并将其与原始文件进行比较
for i in `find -wholename "*.txt"`; do
sed 's/foo/bar/g' ${i} > ${i}.new;
diff -u ${i} ${i}.new;
done
如果更改看起来正常,请将新文件移到其原始名称
for i in `find -wholename "*.new"` ; do
mv ${i} ${i/.new};
done
所有这些都可以用和来完成。只需稍作修改:
find -path "*.txt" -exec sed -i.bak 's/foo/bar/g' {} +
这会调用最大数量的文件(注意+
在-exec
末尾),因此不需要。在-i.bak
中,执行就地编辑,将原始文件重命名为.bak
。因此,如果需要,您可以稍后检查差异
在man find
中可以阅读:
-wholename pattern
See -path. This alternative is less portable than -path.
所有这些都可以用和来完成。只需稍作修改:
find -path "*.txt" -exec sed -i.bak 's/foo/bar/g' {} +
这会调用最大数量的文件(注意+
在-exec
末尾),因此不需要。在-i.bak
中,执行就地编辑,将原始文件重命名为.bak
。因此,如果需要,您可以稍后检查差异
在man find
中可以阅读:
-wholename pattern
See -path. This alternative is less portable than -path.
你可以使用emacs:。谢谢@J.F.Sebastian提供的信息,但我是一个vim人:~你可以删除-I
并将所有内容重定向到一个文件。如果一切正常,执行原始命令。另请参见@devnull:谢谢你的指点。我刚试过,但它似乎输出了整个文件,而不是被替换的部分@@@“,知道如何修复它吗@@@”对所有回答我问题的优秀人士说:很抱歉,我今天的票数用完了,一旦我可以再次投票,我将投票支持你的答案:~~你可以使用emacs:。谢谢@J.F.Sebastian提供信息,但我是vim的人:~你可以删除-I
并将所有内容重定向到一个文件。如果一切正常,执行原始命令。另请参见@devnull:谢谢你的指点。我刚试过,但似乎它输出的是整个文件,而不是被替换的部分@@@“,你知道如何修复它吗@@@”对于所有回答我问题的优秀人士:很抱歉,我今天的票数不足,我将在再次投票后投票支持你的答案:~~谢谢你的回答。但是输出与我的解决方案有相同的问题,有没有办法知道哪个文件包含输出?@keelar为打印文件名添加了awk
解决方案谢谢,我正在尝试您的解决方案,但在/foo之后出现语法错误print
/{
。我做错什么了吗?@keelar添加了一个示例testSure,find-wholename“*.txt”| xargs gawk-I inplace'/foo/{print FILENAME;gsub(/foo/,“bar”);print}“
谢谢你的回答。但是输出与我的解决方案有相同的问题,有没有办法知道哪个文件包含输出?@keelar添加了打印文件名的awk
解决方案谢谢,我正在尝试你的解决方案,但在/foo之后出现语法错误print
”/{
。我做错什么了吗?@keelar添加了一个示例testSure,find-wholename“*.txt”| xargs gawk-I inplace'/foo/{print FILENAME;gsub(/foo/,“bar”);print}'