正则表达式搜索和替换多个文件

问题描述:

我需要重构跨多个文件夹中存储的多个PHP文件的一些代码。正则表达式搜索和替换多个文件

我需要更换喜欢的代码实例:

trim(ucfirst($userinfo['first_name'])).' '.trim(ucfirst($userinfo['last_name'])) 

对于文本(的地方,在这些文件中)为:

formatUserName($userinfo['first_name'],$userinfo['last_name']) 

注意,$变量名会有所不同,但一切否则将是相同的*。

我在一台Windows机器上,但安装了PHP和Perl - 宁愿使用它而不是sed。

我有Notepad ++,但不知道是否可以处理这样的搜索和替换操作。

*我们的代码中有这样一行代码的变体,一旦我理解了如何构建正确的正则表达式,我将自行尝试。

+2

什么是你的问题? – TLP 2012-04-20 12:47:38

+2

我们在谈论多少个文件?如果是在合理的范围内,你可以简单地使用一个编辑器,让你创建一个项目(向其中添加所有文件),并在项目中的所有文件上运行查找和替换(我使用PSPad)。然后在名称变量上查找,以检查是否更新了此问题的所有实例。 – Armatus 2012-04-20 12:48:04

+0

@将 - 这是一个编程问题 - 我试图确定使用适当的正则表达式。 – siliconpi 2012-04-21 01:12:23

用记事本++ 6.0的版本,你可以这样做:

查找:formatUserName\(\1,\2\)

+0

我认为它需要是formatUserName(\ 1,\ 2) – siliconpi 2012-04-20 13:16:29

+0

@SidB:良好的捕获,回答编辑。 – Toto 2012-04-20 13:19:37

+0

它工作真棒......! :D – siliconpi 2012-04-20 13:36:30

我假设你的问题是关于如何处理元字符。这是一种方法。

my $find = q|trim(ucfirst($userinfo['first_name'])).' '.trim(ucfirst($userinfo['last_name']))|; 
my $replace = q|formatUserName($userinfo['first_name'],$userinfo['last_name'])|; 

while (<>) { 
    s/\Q$find\E/$replace/g; 
} 

\Q ... \E将导致正则表达式匹配里面是什么,它确实,虽然变数仍然插值。

+0

问题说变量名称是不同的。 – daxim 2012-04-20 13:04:00

+0

@daxim这个问题说了很多东西。我回答了关于元字符的部分。 – TLP 2012-04-20 13:08:41

+0

是的,变量名称$ userinfo将是$ admininfo,$ insinfo等等。但是它将在'first_name'和'last_name'之间相同。 – siliconpi 2012-04-20 13:08:56

未经测试(没有Windows外壳可用):

perl -i.bak -lpe"BEGIN { $varname = qr/\$[a-z]+/; } s/trim\(ucfirst\(($varname)\['first_name'\]\)\)\.' '\.trim\(ucfirst\(\1\[\'last_name'\]\)\)/formatUserName($1['first_name'],$1['last_name'])/;" file1.php file2.php file3.php … 

注意trim\(ucfirst\((\$\w+\['first_name'\])\)\)\.' '\.trim\(ucfirst\((\$\w+\['last_name'\])\)\)

与更换\1 backref在匹配部分和$1捕获缓冲区在subst部分。

+1

Windows外壳不会自动为您设置参数。另外WIndows Perl不会让你在没有备份文件的情况下进行就地编辑:你需要'-i.bak'或类似的文件。 – Borodin 2012-04-20 13:11:32

脚本:

$_ = 'trim(ucfirst($userinfo[\'first_name\'])).\' \'.trim(ucfirst($userinfo[\'last_name\']))'; 
s/^trim\(ucfirst\((\$[^\)]+)\)\)\.'\s+'\.trim\(ucfirst\((\$[^\)]+)\)\)$/formatUserName($1,$2)/; 
print $_; 

输出:

formatUserName($userinfo['first_name'],$userinfo['last_name']) 

测试环节:http://ideone.com/4e0Bf

也许是最好的办法是使用File::Find模块来填充@ARGV,然后只需在while (<>)循环内进行替换。

该程序显示的想法,但我没有测试过正则表达式,所以要小心。这些文件的备份副本将被保存为*.php.bak

use strict; 
use warnings; 

use File::Find; 

our @ARGV =(); 

find sub { 
    push @ARGV, $File::Find::name if /\.php$/; 
}, 'C:\path\to\tree\root'; 

$^I = '.bak'; 

while (<>) { 
    s<\Qtrim(ucfirst(\E\$(\w+)\Q['first_name'])).' '.trim(ucfirst(\E\$\1\Q['last_name']))\E> 
    <formatUserName(\$$1['first_name'],\$$1['last_name'])>g; 
    print; 
}