我正在将包含相当简单的 ASP 代码的文件目录迁移到 PHP 服务器,并且需要使用查找和替换机制修改所有文件的内容。我不太擅长正则表达式,但我已经用它来改变了一些事情:
find . -name "*.php" -print0 | xargs -0 -n 1 sed -i -e 's/oldstring/newstring/g'
我有一些复杂的字符串需要替换。请参阅以下内容:
从:
<% if request("page") = "" then %>
到:
<?php if(!isset($_GET['page']) || !$_GET['page']){ ?>
这一个,* 可以是任何数字,然后将该数字保留在“TO”上* 所在的位置。
从:
<% elseif request("page") = "*" then %>
到:
<?php } elseif($_GET['page'] == '*'){ ?>
最后一个非常简单。从:
<% end if %>
到:
<?php } ?>
如果我可以在目录中递归地批量运行它,这将修复这些文件中 98% 的 ASP 代码。我尝试以多种方式转义这些字符串,但无法弄清楚如何让它运行。任何帮助表示赞赏!
答案1
有多种方法可以做到这一点,我建议利用 Perl 的quotemeta
功能。
首先,制作一个制表符分隔文本文件,其中包含第一列中的搜索模式及其第二列中的替换:
$ cat pats.txt
<% if request("page") = "" then %> <?php if(!isset($_GET['page']) || !$_GET['page']){ ?>
<% elseif request("page") = "*" then %> <?php } elseif($_GET['page'] == '*'){ ?>
<% end if %> <?php } ?>
我创建了一个测试文件,其内容是:
$ cat foo.asp
<% if request("page") = "" then %>
<% elseif request("page") = "*" then %>
<% end if %>
Perl 来拯救:
find . -name "*.php" | while IFS= read -r file; do
perl -i.bak -e 'open(A,"pats.txt");
while(<A>){chomp; @a=split(/\t/); $k{quotemeta($a[0])}=$a[1]}
while(<>){
foreach $pat (keys(%k)){
s/$pat/$k{$pat}/;
}
print}' $file;
done
Perl 的-i
标志的工作方式就像在 中一样sed
,您可以指定一个可选的备份后缀。在上面的示例中,foo.php.bak
将为每个处理的文件创建一个名为 的文件。-i
如果您不需要备份,请单独使用。
解释:
该脚本将读取模式和替换,并将模式保存为散列 ( %k
) 的键,其中替换是值。该quotemeta
函数转义所有非 ASCII(不匹配[A-Za-z_0-9]
)字符。
他们的脚本打开第二个文件,查找每行中的每个模式并进行相应的替换。由于搜索模式已被转义,quotemeta
因此可以正确识别。
笔记
这显然不是最有效的方法,因为它必须查找每行上的每个模式。尽管如此,它还是有效的,并且比尝试手动逃避一切要简单得多。
对于名称中包含新行的文件,该脚本将失败。我想这在这里不会成为问题。