Regex 使用sed和find在多个文件中进行更改

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 \

我必须浏览100多个站点,并在所有站点(sendmail1.php)的同一个文件中添加两行内容。 老板想让我手工复制/粘贴这些东西,但必须有一种更简单的方法,所以我尝试使用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并测试脚本时对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
命令才会输出任何内容。如果它们与选定的单个文件相同,则它们都相同。:)谢谢。这将定义