Regex 使用sed和find在多个文件中进行更改
我必须浏览100多个站点,并在所有站点(sendmail1.php)的同一个文件中添加两行内容。 老板想让我手工复制/粘贴这些东西,但必须有一种更简单的方法,所以我尝试使用find和sed来完成,这两种方法显然我用得不好。我只想在目录中运行一个脚本,其中包含所有站点所在的目录 我有这个:Regex 使用sed和find在多个文件中进行更改,regex,bash,sed,find,Regex,Bash,Sed,Find,我必须浏览100多个站点,并在所有站点(sendmail1.php)的同一个文件中添加两行内容。 老板想让我手工复制/粘贴这些东西,但必须有一种更简单的方法,所以我尝试使用find和sed来完成,这两种方法显然我用得不好。我只想在目录中运行一个脚本,其中包含所有站点所在的目录 我有这个: #!/bin/bash read -p "Which file, sir? : " file # find . -depth 1 -type f -name 'sendmail1.php' -exec \
#!/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并测试脚本时对find进行了注释,但我想解决这两个问题。
我想我并没有在sed
位中逃避一些必要的东西,但我不断地检查和更改它,并得到不同的错误(有时是“未完成的s/语句”,有时是其他的东西)
关键是我必须这样做:
在的右下方需要dirname(_文件)'/includes/validate.php'
,添加以下行:
require_once dirname(__FILE__).'/includes/carriersoft_email.php';
$carriersoft_sent = carriersoft_email();
及
在下的else if($\u POST['email']&($\u POST['work\u email']==”){
,添加此行:
require_once dirname(__FILE__).'/includes/carriersoft_email.php';
$carriersoft_sent = carriersoft_email();
我想把这个4小时的复制/面食噩梦变成一个2分钟的懒惰管理员类型的脚本,并完成它的工作。
但我的傅不擅长sed或是发现。。。
至于发现,我得到“路径必须在表达式之前: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
选项组合为一个。请尝试以下操作:
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
来输出,会更加清晰e更改文件,创建包含以下内容的脚本(例如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-fscript.sed sendmail1.php
要在所有文件中应用更改,请运行:
find . -name 'sendmail1.php' -exec sed -i -f script.sed {} \;
(-i
导致sed
就地更改文件)
在这样的操作中,最好在运行命令后进行备份并检查确切的更改。我认为如果使用另一个精细的命令
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-fscript.sed sendmail1.php
要在所有文件中应用更改,请运行:
find . -name 'sendmail1.php' -exec sed -i -f script.sed {} \;
(-i
导致sed
就地更改文件)
在此类操作中,建议在运行命令后进行备份并检查准确的更改。:)保持简单,只需使用awk,因为awk可以使用字符串操作,而sed只在REs上工作,但需要附加注意事项:
find whatever |
while IFS= read -r file
do
awk '
{ print }
index($0,"require dirname(__FILE__).\047/includes/validate.php\047;") {
print "require_once dirname(__FILE__).\047/includes/carriersoft_email.php\047;"
}
index($0,"else if($_POST[\047email\047] && ($_POST[\04work_email\047] == "")){") {
print "$carriersoft_sent = carriersoft_email();"
}
' "$file" > /usr/tmp/tmp_$$ &&
mv /usr/tmp/tmp_$$ "$file"
done
使用GNU awk,您可以使用-i inplace
避免手动指定tmp文件名,就像使用sed-i
一样
\047
s是在单引号分隔的脚本中指定单引号的一种方法。保持简单,只需使用awk,因为awk可以与字符串一起操作,而sed只在REs上工作,但需要附加注意事项:
find whatever |
while IFS= read -r file
do
awk '
{ print }
index($0,"require dirname(__FILE__).\047/includes/validate.php\047;") {
print "require_once dirname(__FILE__).\047/includes/carriersoft_email.php\047;"
}
index($0,"else if($_POST[\047email\047] && ($_POST[\04work_email\047] == "")){") {
print "$carriersoft_sent = carriersoft_email();"
}
' "$file" > /usr/tmp/tmp_$$ &&
mv /usr/tmp/tmp_$$ "$file"
done
使用GNU awk,您可以使用-i inplace
避免手动指定tmp文件名,就像使用sed-i
一样
\047
是在单引号分隔的脚本中指定单引号的一种方法。“(…)在所有脚本中向同一文件添加两行(…)”-那么,只更改一个文件并将其复制到所有其他位置不是更容易吗?文件的其他部分可能存在其他特定于站点的差异。我问老板:“为什么不将编辑过的文件复制到所有这些位置?”虽然我有一些不同,但找不到任何差异。好的。我刚刚收到老板的回复:“我更喜欢编辑每个文件,我不确定我们可能已经为其他特定网站进行了哪些定制。”好的,但仅供参考:检查所有这些文件是否相同很容易-只需选择其中一个并将其与所有其他文件进行比较:find.-name'sendmail1.php'-exec diff-q path/to/reference/senmail1.php{}\;
(用所选文件替换path/to/reference/senmail1.php
)。只有当文件不同时,diff
命令才会输出任何内容。如果它们与所选的单个文件相同,则它们都是相同的。:)谢谢。这肯定会派上用场。这些人按小时向我支付工资,并为这项工作编列了5个小时的预算,因此我只需按时间计算,但我更愿意以效率让他们眼花缭乱。”(…)在所有文件中向同一个文件添加两行(…)“-那么只更改一个文件并将其复制到所有其他位置不是更容易吗?文件的其他部分可能存在其他特定于站点的差异。当我问老板“我为什么不将编辑过的文件复制到所有这些位置?”虽然我有一些不同,但找不到任何差异。好的。我刚刚收到老板的回复:“我更喜欢编辑每个文件,我不确定我们可能已经为其他特定网站进行了哪些定制。”好的,但仅供参考:检查所有这些文件是否相同很容易-只需选择其中一个并将其与所有其他文件进行比较:find.-name'sendmail1.php'-exec diff-q path/to/reference/senmail1.php{}\;
(用所选文件替换path/to/reference/senmail1.php
)。仅当文件不同时,diff
命令才会输出任何内容。如果它们与选定的单个文件相同,则它们都相同。:)谢谢。这将定义