我很难理解\G锚如何在正则表达式的PHP风格中起作用.
我倾向于认为(即使我可能错了),\G而不是^在相同字符串的多个匹配发生的情况下使用.
有人可以展示一个\G应该如何使用的例子,并解释它是如何以及为什么有效的?
UPDATE
\ G强制模式仅返回作为连续匹配链的一部分的匹配.从第一场比赛开始,每场后续比赛必须先进行比赛.如果你打破链条,比赛结束.
<?php
$pattern = '#(match),#';
$subject = "match,match,match,match,not-match,match";
preg_match_all( $pattern, $subject, $matches );
//Will output match 5 times because it skips over not-match
foreach ( $matches[1] as $match ) {
echo $match . '<br />';
}
echo '<br />';
$pattern = '#(\Gmatch),#';
$subject = "match,match,match,match,not-match,match";
preg_match_all( $pattern, $subject, $matches );
//Will only output match 4 times because at not-match the chain is broken
foreach ( $matches[1] as $match ) {
echo $match . '<br />';
}
?>
Run Code Online (Sandbox Code Playgroud)
这直接来自文档
反斜杠的第四个用法是用于某些简单的断言.断言指定必须在匹配中的特定点处满足的条件,而不消耗主题字符串中的任何字符.下面描述了使用子模式进行更复杂的断言.反向断言是
\G
first matching position in subject
Run Code Online (Sandbox Code Playgroud)
仅当当前匹配位置位于匹配的起始点时,\ G断言才为真,如preg_match()的偏移参数所指定.当offset的值不为零时,它与\ A不同.
http://www.php.net/manual/en/regexp.reference.escape.php
您将不得不向下滚动该页面,但它确实存在.
在ruby中有一个非常好的例子,但它在php中是相同的.
\G 将匹配匹配边界,该边界要么是字符串的开头,要么是消耗最后匹配的最后一个字符的点。
当您需要进行复杂的令牌化时,同时还要确保令牌有效时,它特别有用。
示例问题
让我们以标记此输入为例:
input 'some input in quote' more input '\'escaped quote\'' lots@_$of_fun ' \' \\ ' crazy'stuff'
Run Code Online (Sandbox Code Playgroud)
放入这些标记(我~用来表示字符串的结尾):
input~
some input in quote~
more~
input~
'escaped quote'~
lots@_$of_fun~
' \ ~
crazy~
stuff~
Run Code Online (Sandbox Code Playgroud)
该字符串由以下各项组成:
\和进行转义,并且'保留空格。可以使用单引号字符串指定空字符串。\或'。为了简单起见,让我们假设输入不包含换行符(实际上,您需要考虑换行符)。这将增加正则表达式的复杂性,而无需说明这一点。
但是,单引号字符串的RAW正则表达式为,'(?:[^\\']|\\[\\'])*+'
而单引号字符串的RAW正则表达式为。[^\s'\\]++
您不必太在意上面的2个正则表达式。
下面的解决方案\G可以确保当引擎无法找到任何匹配项时,从字符串开头到最后一个匹配项的所有字符都将被消耗。由于无法跳过字符,因此当引擎无法找到两种令牌规格的有效匹配项时,引擎将停止匹配,而不是在字符串的其余部分中获取随机内容。
施工
在构建的第一步,我们可以将以下正则表达式放在一起:
\G(?:'((?:[^\\']|\\[\\'])*+)'|([^\s'\\]++))
Run Code Online (Sandbox Code Playgroud)
或简单地说(这不是正则表达式-只是为了使其更易于阅读):
\G(Singly_quote_regex|Unquoted_regex)
Run Code Online (Sandbox Code Playgroud)
这将仅匹配第一个令牌,因为当它第二次尝试匹配时,匹配将在之前的空格处停止'some input...。
我们只需要添加一点以允许0或更多的空间,以便在随后的匹配中,消耗上一次匹配保留的位置的空间:
\G *+(?:'((?:[^\\']|\\[\\'])*+)'|([^\s'\\]++))
Run Code Online (Sandbox Code Playgroud)
正则表达式上面现在将正确地识别标记,比如看到这里。
可以对正则表达式进行进一步修改,以便在引擎无法检索任何有效令牌时返回正则表达式的其余部分:
\G *+(?:'((?:[^\\']|\\[\\'])*+)'|([^\s'\\]++)|((?s).+$))
Run Code Online (Sandbox Code Playgroud)
由于交替是按从左到右的顺序进行的,因此((?s).+$),仅当前面的字符串没有组成有效的单引号或无引号的标记时,最后一种选择才会匹配。这可以用来检查错误。
第一个捕获组将在单引号字符串内包含文本,这需要额外的处理才能转换为所需的文本(此处并不实际相关,因此我将其留给读者练习)。第二个捕获组将包含未引用的字符串。第三捕获组充当输入字符串无效的指示。
结论
上面的示例演示了\G令牌化中使用的一种情况。可能还有我没有遇到过的其他用法。
| 归档时间: |
|
| 查看次数: |
5641 次 |
| 最近记录: |