使用 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
是一种在单引号分隔的脚本中指定单引号的方法。
我必须浏览 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
是一种在单引号分隔的脚本中指定单引号的方法。