Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Perl中带*修饰符的负先行断言_Regex_Perl_Negative Lookahead_Regex Lookarounds - Fatal编程技术网

Regex Perl中带*修饰符的负先行断言

Regex Perl中带*修饰符的负先行断言,regex,perl,negative-lookahead,regex-lookarounds,Regex,Perl,Negative Lookahead,Regex Lookarounds,我有一个(我认为是)消极的前瞻断言*(?!QQQ),如果测试的字符串是一个,后跟任意数量的空格(包括零),然后不后跟QQQ,我希望匹配这个断言 但是,如果测试的字符串是QQQ,则正则表达式匹配 我不明白为什么会出现这种情况,如果能在这件事上得到任何帮助,我将不胜感激 这是一个测试脚本 use warnings; use strict; my @strings = ('something <@> QQQ', 'something <@> RR

我有一个(我认为是)消极的前瞻断言
*(?!QQQ)
,如果测试的字符串是一个
,后跟任意数量的空格(包括零),然后不后跟
QQQ
,我希望匹配这个断言

但是,如果测试的字符串是
QQQ
,则正则表达式匹配

我不明白为什么会出现这种情况,如果能在这件事上得到任何帮助,我将不胜感激

这是一个测试脚本

use warnings;
use strict;

my @strings = ('something <@> QQQ',
               'something <@> RRR',
               'something <@>QQQ' ,
               'something <@>RRR' );


print "$_\n" for map {$_ . " --> " . rep($_) } (@strings);



sub rep {

  my $string = shift;

  $string  =~ s,<@> *(?!QQQ),at w/o ,;
  $string  =~ s,<@> *QQQ,at w/  QQQ,;

  return $string;
}
使用警告;
严格使用;
我的@strings=('something QQQ',
“某物RRR”,
“什么QQQ”,
"注册登记";;
为映射{$\.-->.rep($\)}(@strings)打印“$\\ n”;
副代表{
我的$string=shift;
$string=~s,*(?!QQQ),在w/o处,;
$string=~s,*QQQ,位于w/QQQ,;
返回$string;
}
这张照片

something <@> QQQ --> something at w/o  QQQ
something <@> RRR --> something at w/o RRR
something <@>QQQ --> something at w/  QQQ
something <@>RRR --> something at w/o RRR
something QQQ-->不带QQQ的某物
某物RRR-->无RRR的某物
某物QQQ-->某物在w/QQQ
某物RRR-->无RRR的某物

我希望第一行是
something QQQ-->在w/QQQ

匹配的东西,因为“任意数”中包含零。所以没有空格,后面跟一个空格,匹配“任何数量的不跟Q的空格”

您应该添加另一个前瞻性断言,即空格后面的第一个东西本身不是空格。试试这个(未经测试):

*(?!QQQ)(?!)
ETA旁注:只有当正好有一个空格时,将量词改为+才有帮助;在一般情况下,正则表达式总是可以少占一个空间,从而获得成功。正则表达式想要匹配,并且会尽可能地向后弯曲以实现匹配。所有其他考虑因素(最左边的、最长的等)都放在次要位置——如果它可以匹配多条路径,则它们决定选择哪条路径。但匹配总是胜过不匹配

$string  =~ s,<@> *(?!QQQ),at w/o ,;
$string  =~ s,<@> *QQQ,at w/  QQQ,;
您必须始终小心使用
*
量词。因为它匹配零次或多次,所以它也可以匹配空字符串,这基本上意味着:它可以匹配任何字符串中的任何位置

否定环顾断言也有类似的性质,即它只需要找到一个不同的东西来匹配。在这种情况下,它将部分
匹配为
+无空格+空格,其中空格当然是“not”
QQQ
。在这里,您或多或少处于一种逻辑僵局,因为
*
量词和否定的前瞻性相互抵消

我相信解决这个问题的正确方法是分离正则表达式,就像我在上面展示的那样。允许两个正则表达式都被执行是没有意义的

然而,出于理论目的,需要锚定一个工作正则表达式,该正则表达式既允许任意数量的空格,也允许负前瞻。就像我们所展示的那样。这个可能是最简单的

<@>(?! *QQQ)        # Add the spaces to the look-ahead

这将起作用,因为任何一个量词都可以匹配空字符串。从理论上讲,您可以根据需要添加任意数量的代码,这不会产生任何影响(性能除外):
/***/
在功能上等同于
/*/
。这里的区别是,与Qs组合的空格可能不存在。

正则表达式引擎将回溯,直到找到匹配项,或者直到无法找到匹配项为止。在本例中,它发现以下匹配项:

                         +--------------- Matches "<@>".
                         |   +----------- Matches "" (empty string).
                         |   |       +--- Doesn't match " QQQ".
                         |   |       |
                        --- ----    ---
'something <@> QQQ' =~ /<@> [ ]* (?!QQQ)/x
+--------------匹配“”。
|+-------------匹配“”(空字符串)。
||+---与“QQQ”不匹配。
|   |       |
--- ----    ---
'something QQQ'=~/[]*(?!QQQ)/x
你所需要做的就是把事情弄得乱七八糟。替换

/<@>[ ]*(?!QQQ)/
/[]*(?!QQQ)/

/(?![]*QQQ)/
或者可以使正则表达式只匹配所有空格:

/<@>[ ]*+(?!QQQ)/
/<@>[ ]*(?![ ]|QQQ)/
/<@>[ ]*(?![ ])(?!QQQ)/
/[]*+(?!QQQ)/
/[]*(?![]| QQQ)/
/[]*(?![])(?!QQQ)/

PS-空格很难看到,所以我使用
[]
使它们更可见。无论如何,它都会得到优化。

(?=\S)
应该是
(?=[^])
(如果下一个字符是制表符)。实际上,它应该是
(?!)
(以防它是字符串的结尾)。添加
+
可以修复匹配,但我不知道为什么。等等,我想我找到了
[]*+
确保即使打破了匹配,也能抓取所有可用的空格,而
[]*
将在不打破匹配的情况下抓取尽可能多的空格。@flies,因为
=“=~/*+/
只能匹配
。它不会回溯到匹配的
”,因此它无法再找到匹配的
/*/
/*+/
应该表示“查找零个或多个空格,一次或多次”,这到底是如何工作的?关于
+
贪婪并占用多余空间的内容?@TLP,不,当
+
应用于量词(例如
*
)时,它会阻止通过该量词进行回溯。(有点像
如何修改
*
的贪婪)
/*+/
/(?>*)/
是一样的。
                         +--------------- Matches "<@>".
                         |   +----------- Matches "" (empty string).
                         |   |       +--- Doesn't match " QQQ".
                         |   |       |
                        --- ----    ---
'something <@> QQQ' =~ /<@> [ ]* (?!QQQ)/x
/<@>[ ]*(?!QQQ)/
/<@>(?![ ]*QQQ)/
/<@>[ ]*+(?!QQQ)/
/<@>[ ]*(?![ ]|QQQ)/
/<@>[ ]*(?![ ])(?!QQQ)/