管道问题找到sed(查找和替换)

时间:2015-11-25 18:03:05

标签: bash sed

这是我当前的代码,我的目标是找到给定目录中的每个文件(递归地)并替换" FIND"用" REPLACEWITH"并覆盖文件。

FIND='ALEX'
REPLACEWITH='<strong>ALEX</strong>'

DIRECTORY='/some/directory/'

find $DIRECTORY -type f -name "*.html" -print0  |
 LANG=C xargs -0  sed  -i "s|$FIND|$REPLACEWITH|g" 

我得到的错误是:

sed: 1: "/some/directory ...": command a expects \ followed by text

2 个答案:

答案 0 :(得分:2)

BashFAQ #21中所述,您可以使用perl执行搜索和替换操作,而不会将数据视为代码:

in="$FIND" out="$REPLACEWITH" find "$DIRECTORY" -type f -name '*.html' \
  -exec perl -pi -e 's/\Q$ENV{"in"}/$ENV{"out"}/g' '{}' +

如果您只想包含与FIND字符串匹配的文件,可以告诉find仅将grep标记的文件传递到perl

in="$FIND" out="$REPLACEWITH" find "$DIRECTORY" -type f -name '*.html' \
  -exec grep -F -q -e "$FIND" '{}' ';' \
  -exec perl -pi -e 's/\Q$ENV{"in"}/$ENV{"out"}/g' '{}' +

由于grep用于评估单个文件,因此必须对每个文件使用一次grep调用,以便可以基于每个文件评估其退出状态。因此,使用效率较低的-exec ... {} ';'动作。对于perl,可以在一个命令上放置多个文件,因此使用-exec ... {} +

请注意fgrep是面向行的;如果您的FIND字符串包含多行,则包含这些行中任意一行的文件将传递到perl以进行替换。

答案 1 :(得分:1)

您可以find直接调用sed,但我认为您文件的所有修改时间都会受到影响(这可能很重要或不重要):

find $DIRECTORY -type f -name "*.html" -exec sed -i "s|$FIND|$REPLACEWITH|g" '{}' ';'