Regex Perl正则表达式替换不使用全局修饰符

Regex Perl正则表达式替换不使用全局修饰符,regex,perl,cygwin,Regex,Perl,Cygwin,我有如下代码: s/(["\'])(?:\\?+.)*?\1/(my $x = $&) =~ s|^(["\'])(.*src=)([\'"])\/|$1$2$3$1.\\$baseUrl.$1\/|g;$x/ge 忽略最后一位(只留下出现问题的部分),代码变为: s/(["\'])(?:\\?+.)*?\1/replace-text-here/g 我已经尝试过使用这两种方法,但我仍然遇到同样的问题,即即使我使用了g修饰符,这个正则表达式也只匹配并替换第一个匹配项。如果这是一个Per

我有如下代码:

s/(["\'])(?:\\?+.)*?\1/(my $x = $&) =~ s|^(["\'])(.*src=)([\'"])\/|$1$2$3$1.\\$baseUrl.$1\/|g;$x/ge
忽略最后一位(只留下出现问题的部分),代码变为:

s/(["\'])(?:\\?+.)*?\1/replace-text-here/g
我已经尝试过使用这两种方法,但我仍然遇到同样的问题,即即使我使用了g修饰符,这个正则表达式也只匹配并替换第一个匹配项。如果这是一个Perl错误,我不知道,但我使用了一个正则表达式,它匹配两个引号之间的所有内容,并且还处理转义引号,我正在跟踪。在我看来,正则表达式应该匹配两个引号之间的所有内容,然后替换它,然后尝试找到这个模式的另一个实例,因为g修饰符

关于一些背景信息,我没有使用和版本声明,严格和警告是打开的,但没有显示任何警告。我的脚本将整个文件读入标量(包括换行符),然后正则表达式直接对该标量进行操作。它似乎在每一行上都能单独工作,只是在一行上不能多次工作。Perl版本5.14.2,在Cygwin 64位上运行。可能是Cygwin(或Perl端口)弄乱了什么,但我对此表示怀疑

我还尝试了那篇博文中的另一个例子,原子组和所有格量词被替换为等效代码,但没有这些特性,但这个问题仍然困扰着我

示例:

<?php echo ($watched_dir->getExistsFlag())?"":"<span class='ui-icon-alert'><img src='/css/images/warning-icon.png'></span>"?>
Should become (with the shortened regex):
<?php echo ($watched_dir->getExistsFlag())?replace-text-here:replace-text-here?>
Yet it only becomes:
<?php echo ($watched_dir->getExistsFlag())?replace-text-here:"<span class='ui-icon-alert'><img src='/css/images/warning-icon.png'></span>"?>

<?php echo ($sub->getTarget() != "")?"target=\"".$sub->getTarget()."\"":""; ?>
Should become:
<?php echo ($sub->getTarget() != replace-text-here)?replace-text-here.$sub->getTarget().replace-text-here:replace-text-here; ?>
And as above, only the first occurrence is changed.
这将为我生成以下输出:

this is the first line, where nothing much happens
but on the second line "we suddenly have some double quotes"
and on the third line there are 'single quotes'
but the fourth line has "double quotes" AND 'single quotes', but also another "double quote"
the fifth line has the interesting one - "double quoted string 'with embedded singles' AND \"escaped doubles\""
and the sixth is just to say - we need a new line at the end to simulate a properly structured file

this is the first line, where nothing much happens
but on the second line "we suddenly have some double quotes"
and on the third line there are 'single quotes'
but the fourth line has "double quotes" AND 'single quotes', but also another "double quote"
the fifth line has the interesting one - "double quoted string 'with embedded singles' AND \"escaped doubles\replaced!
and the sixth is just to say - we need a new line at the end to simulate a properly structured file

this is the first line, where nothing much happens
but on the second line replaced2!
and on the third line there are replaced2!
but the fourth line has replaced2! AND replaced2!, but also another replaced2!
the fifth line has the interesting one - replaced2!escaped doubles\replaced2!
and the sixth is just to say - we need a new line at the end to simulate a properly structured file
更新:此:

my $regex = 's/(["\'])(?:\\?+.)*?\1/replaced!/g';
应该是:

my $regex = 's/(["\'])(?:\\\\?+.)*?\1/replaced!/g';
由于赋值中的单引号将
\\
转换为
\
,您希望正则表达式以
\\
结尾

请将您的问题归结为演示问题的简短脚本(包括输入、错误输出、评估和所有)。拿着你的表演并尝试:

use strict;
use warnings;
my $input = <<'END';
<?php echo ($watched_dir->getExistsFlag())?"":"<span class='ui-icon-alert'><img src='/css/images/warning-icon.png'></span>"?>
END

(my $output = $input) =~ s/(["\'])(?:\\?+.)*?\1/replace-text-here/g;
print $input,"becomes\n",$output;
使用严格;
使用警告;

my$input=即使在单引号中,
\\
也会作为
\
处理,因此:

my $regex = 's/(["\'])(?:\\?+.)*?\1/replaced!/g';
$regex
设置为:

s/(["'])(?:\?+.)*?\1/replaced!/g
它要求带引号的字符串中的每个字符前面都有一个或多个文字问号(
\?+
)。由于没有太多问号,这实际上意味着您要求字符串为空,

最小的解决方案是添加更多反斜杠:

my $regex = 's/(["\'])(?:\\\\?+.)*?\\1/replaced!/g';

但你可能真的想重新考虑你的方法。您真的需要将整个regex replacement命令保存为字符串,并通过
eval
运行它吗?

这将有助于显示应用此替换的数据示例。将第二次替换应用于
q(“aaa”'bbb')
会导致“此处替换文本此处替换文本”`我认为这正是您打算使用的
(?:\\\1?)*?
而不是
(?:\?+)*?
@Borodin该页面实际上说明特定正则表达式存在“问题”,并在实际使用中使用edit2。编辑2是我的正则表达式。啊,我明白了。但是,您仍然需要向我们提供一个与代码不兼容的数据示例。请不要计算regexp字符串,因为这样您将不得不执行额外的引用。如果要控制何时调用regexp,只需将其放入子对象中:
subregexp{$\[0]=~s/../../…/ge}
,然后在执行替换时只需使用
regexp($data)
。这将产生与生成正确输出的
$data=~s/../../..//ge
相同的效果。我认为这与我的评估有关——将正则表达式直接放进去产生正确的结果——在评估中使用它会把事情搞砸。@Xenopathic:好吧,你的例子让你的问题变得很明显。更新我的答案。谢谢你的帮助!逃逸者解决了这个问题。你比ruakh慢了2分钟回答问题,所以不幸的是,答案要归功于他。太棒了!谢谢你。我之所以将其保存为字符串,是因为我的代码根据某些条件将文件拆分为若干小段,然后根据该段的“上下文”运行某个命令(在本例中为regex)——例如,between保存为php上下文,php regex在其上运行。反过来,还有一个html正则表达式和一个js正则表达式。@Xenopathic:不客气!Re:为什么要将其保存为字符串:听起来您要查找的是匿名子例程和/或子例程引用。(谷歌这些术语中的任何一个,加上“Perl”,以获取详细信息和教程。)@Xenopathic:那么你可能需要一个调度表
s/(["'])(?:\?+.)*?\1/replaced!/g
my $regex = 's/(["\'])(?:\\\\?+.)*?\\1/replaced!/g';