Linux SED搜索替换多个匹配项每行

3
我可以帮您翻译成中文。以下是需要翻译的内容:

我需要用一个由我编写的PHP函数来替换客户网站上的一大堆PHP超级全局变量,以清除超级全局变量中的XSS攻击。

以下是原始代码示例:

echo $_REQUEST['HELLO1'] . ' AND ' . $_REQUEST['HELLO2'];

我需要它看起来像这样:

echo MYCLASS::myfunction($_REQUEST['HELLO1']) . ' AND ' . MYCLASS::myfunction($_REQUEST['HELLO2']);

主要问题是我需要在100多个文件中进行搜索/替换!太可怕了!

因此,我的解决方案是(在Linux shell中):

sudo sed -i 's/\$_REQUEST[.*\]/MYCLASS::myfunction(&)/g' *.php

只要每行中只出现一次"$_REQUEST",这个方法就能很好地工作... 但是如果有多个实例,它会出现错误,如下所示:
echo MYCLASS::myfunction($_REQUEST['HELLO1'] . ' AND ' . $_REQUEST['HELLO2']);
5个回答

2
问题在于.*是贪婪的,并且会找到它能找到的最长匹配。为了解决这个问题,使用[^]]*代替,这样就不会意外地抓取额外的方括号。
sudo sed -i 's/\$_REQUEST\[[^]]*\]/MYCLASS::myfunction(&)/g' *.php

在其他正则表达式方言中,你也可以写 .*? 来使通配符变成非贪婪模式,但在 sed 中似乎不起作用(至少在我的版本中不起作用,即使使用 sed -r 也不行)。

谢谢你的帮助。.?的概念很有趣。答案不起作用。我们正在尝试.?。谢谢! - Kevin Florida

1
在Perl中,以下脚本将起作用,您可以通过传递文件名来指定您感兴趣的文件
假设脚本是t.pl,您的文件是file.php
要输出回file.php
perl t.pl file.php > file.php
要输出到另一个文件,以便不覆盖原始文件
perl t.pl file.php > another_file.php

#!/usr/bin/perl

$FILE_NAME = $ARGV[0];

open (FILE_NAME) or die ("Could not open FILE_NAME information file: $FILE_NAME \n");
@file_contents = <FILE_NAME>;
close (FILE_NAME);


foreach $line (@file_contents) {
       chomp($line);
       $line =~ s/\$_REQUEST\[.*?\]/MYCLASS\:\:myfunction\($&\)/g;
       print $line." \n";
}

退出;


我不确定是否应该获得解决方案标记,因为我没有使用sed,但很高兴这个Perl脚本对你有用。 - Troy

1

尝试使用这个sed命令:

sed -i.bak 's/\$_REQUEST\[\([^]]*\)\]/MYCLASS::myfunction(\1)/g' *.php

或者用 Perl:

perl -pe 's/\$_REQUEST\[([^]]*)\]/MYCLASS::myfunction(\1)/g' file.php

不客气,我在上面的回答中也提供了一个 Perl 一行代码来完成相同的任务。 - anubhava
我有一个问题.. 它将 $_REQUEST[' '] 替换为 $_REQUEST(' '),你有什么解决方法吗? - Kevin Florida
将myfunction(\1)更改为myfunction([\1]),问题解决了!谢谢! - Kevin Florida
如果其他人有相同的问题,我实际上将其更改为这个myfunction($_REQUEST[\1])。 - Kevin Florida

1

sed 's/\$_REQUEST\[[^]]*\]/MYCLASS::myfunction(&)/g'

sed 's/\$_REQUEST\[[^]]*\]/MYCLASS::myfunction(&)/g'


0

这应该可以:

sed -i "s/\$_REQUEST\[\([^\x5d]*\)\]/MYCLASS::myfunction(\1)/g" *.php

我在匹配]时遇到了很多麻烦,所以我用了\x5d


我遇到了一个问题:“-e expression #1, char 43: invalid reference \1 on `s; command's”。 - Kevin Florida

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接