让我把我的问题分解为最简单的例子。
创建包含一行文本的测试文件。
[root@myserver ] /tmp> echo "test ReplaceMe DoNotReplaceMe" > /tmp/daj.txt
我们有一个现有的find
命令,我们用它来替换匹配它的所有文件中的文本(在这个例子中,我简化了这个命令只能处理一个文件,并删除了其他的东西吧一样)。
问题在于它取代了“ReplaceMe”它出现的任何地方,而不仅仅是它本身就是一个单词。
[root@myserver ] /tmp> find /tmp/daj.txt -exec sh -c 'f="{}"; sed -e 's/ReplaceMe/#DONE#/gi' "${f#.}" ' \;
test #DONE# DoNot#DONE#
我编写了一个新的sed
命令,当它本身是一个单词时,只替换“ReplaceMe”,但不是当它是另一个单词的子串时。此命令的输出是正确的。
[root@myserver ] /tmp> cat /tmp/daj.txt | sed -e 's/\(\W\)\(ReplaceMe\)\(\W\)/\1#DONE#\3/gi'
test #DONE# DoNotReplaceMe
当我尝试将更新的sed
命令合并到find
命令中时,它会中断。看起来我遇到了一个逃避问题,但我没有设法通过增加额外的转义来解决它。
[root@myserver ] /tmp> find /tmp/daj.txt -exec sh -c 'f="{}"; sed -e 's/\(\W\)\(ReplaceMe\)\(\W\)/\1#DONE#\3/gi' "${f#.}" ' \;
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `f="/tmp/daj.txt"; sed -e s/(W)(ReplaceMe)(W)/1#DONE#3/gi "${f#.}" '
有没有办法逃脱我的sed
命令,以便我可以通过find
运行它,或者我是否需要寻找替代解决方案?
更新:我们正在运行的完整find
命令打印出文件名和权限,然后将sed
的输出通过管道传输到md5sum
。以下是运行和匹配多个文件的示例:
[root@myserver ] ~> find /tmp -regex '.*daj.*\.txt' -printf '%p %m ' -exec sh -c 'f="{}"; sed -e 's/ReplaceMe/#DONE#/gi' "${f#.}" | md5sum' \;
/tmp/daj2.txt 644 d52bbd311552234b761bcae694c2055a -
/tmp/daj.txt 644 d52bbd311552234b761bcae694c2055a -
答案 0 :(得分:2)
您不应该直接在shell中使用{}
,而应该将文件名作为shell参数传递。另外,如果您想限制为全字匹配,请使用\<word\>
作为sed
find /tmp -regex '.*daj.*\.txt' -printf '%p %m ' -exec sh -c "sed -e 's/\<ReplaceMe\>/#DONE#/gi' \$@ | md5sum" _ {} \;
$ find . -regex '.*daj.*\.txt' -printf '%p %m ' -exec sh -c "sed -e 's/\<ReplaceMe\>/#DONE#/gi' \$@ | md5sum" _ {} \;
./daj2.txt 664 ea324b4721ed037dbc2402ded4446005 -
./daj.txt 664 0bbb9104da99c1c1187a2a35e6ac0e9b -
答案 1 :(得分:1)
这不能解答有关转义序列的问题,但可以解决问题。我基本上使用xargs
和sed
这样:
$ find ~/tmp/data.txt | xargs sed -e 's/\<replaceme\>/1234/'
1234 in this sentance
donotreplaceme in this sentance
$
和data.txt的内容:
replaceme in this sentance
donotreplaceme in this sentance
此外,如果您使用-print0
参数可能包含空格的文件名,则告诉find将文件列表输出为空终止字符串。否则,find会将文件名中的空格解释为文件名的结尾。然后在使用xargs
时,您需要使用-0
参数告诉xargs输入是一个空终止字符串列表。示例如下:
find /somedir -print0 | xargs -0 command