使用 sed 和查找在多个文件中进行更改

Make changes in multiple files using sed and find

我必须浏览 100 多个站点并在所有站点中的同一个文件中添加两行 (sendmail1.php)。 老板要我交给 copy/paste 这些东西,但必须有更简单的方法,所以我尝试用 find 和 sed 来做,显然我用得不好。我只想 运行 目录中的一个脚本,其中包含包含所有站点的目录。

我有这个:

#!/bin/bash

read -p "Which file, sir? : " file

# find . -depth 1  -type f -name 'sendmail1.php' -exec \


sed -i 's/require\ dirname\(__FILE__\).\'\/includes\/validate.php\';/ \
        a require_once dirname\(__FILE__\).\'\/includes\/carriersoft_email.php\';' $file


sed -i 's/\else\ if\($_POST[\'email\']\ \&\&\ \($_POST\'work_email\'\]\ ==\ \"\"\)\){/ \
        a\t$carriersoft_sent = carriersoft_email\(\);' $file

exit 0

目前,我在尝试整理此处的 sed 和测试脚本时已将发现注释掉,但我想同时解决这两个问题。 我认为我没有在 sed 位中转义某些必要的东西,但我一直在检查它并更改它并得到不同的错误(有时 "unfinished s/ statement" 其他时间。其他东西。

重点是我必须这样做:

require dirname(__FILE__).'/includes/validate.php'; 下方,添加此行:

require_once dirname(__FILE__).'/includes/carriersoft_email.php';

else if($_POST['email'] && ($_POST['work_email'] == "")){ 下,添加此行:

$carriersoft_sent = carriersoft_email();

我想将这 4 小时 copy/pasta 的噩梦变成 2 分钟的懒惰管理员类型脚本并完成工作。 但是我的 fu 对 sed 或 find 并不强大...... 至于查找,我得到 "path must preceed expression: 1" 我在这里找到了解决该错误的问题,但指出使用 '' 包围文件名应该可以解决它,但它不起作用。

试试这个:

sed -e "s/require dirname(__FILE__).'\/includes\/validate.php';/&\nrequire_once dirname(__FILE__).'\/includes\/carriersoft_email.php'\;/" \
-e "s/else if($_POST\['email'\] && ($_POST\['work_email'\] == \"\")){/&\n$carriersoft_sent = carriersoft_email();/"                   \
file

注意:我没有使用 -i 标志。一旦您确认它适合您,您就可以使用 -i 标志。此外,我已将您的两个 sed 命令与 -e 选项合并为一个。

我认为如果您使用另一个很好的命令 a 而不是 s 会更清楚。要输出一个更改的文件,请创建一个包含以下内容的脚本(例如 script.sed):

/require dirname(__FILE__)\.'\/includes\/validate.php';/a\
require_once dirname(__FILE__).'/includes/carriersoft_email.php';
/else if($_POST\['email'\] && ($_POST\['work_email'\] == "")){/a\
$carriersoft_sent = carriersoft_email();

和运行sed -f script.sed sendmail1.php.

要在所有文件中应用更改,运行:

find . -name 'sendmail1.php' -exec sed -i -f script.sed {} \;

-i 导致 sed 就地更改文件)。

在此类操作中,始终建议在 运行 执行命令后进行备份并检查确切的更改。 :)

保持简单,只使用 awk,因为 awk 可以处理字符串,这与 sed 不同,后者仅适用于 RE,但有额外的注意事项:

find whatever |
while IFS= read -r file
do
    awk '
        { print }
        index([=10=],"require dirname(__FILE__).7/includes/validate.php7;") {
            print "require_once dirname(__FILE__).7/includes/carriersoft_email.php7;"
        }
        index([=10=],"else if($_POST[7email7] && ($_POST[work_email7] == "")){") {
            print "$carriersoft_sent = carriersoft_email();"
        }
    ' "$file" > /usr/tmp/tmp_$$ &&
    mv /usr/tmp/tmp_$$ "$file"
done

对于 GNU awk,您可以使用 -i inplace 来避免手动指定 tmp 文件名,就像 sed -i.

7是一种在单引号分隔的脚本中指定单引号的方法。