我需要一个匹配特定捕获组的正则表达式,该捕获组属于多行注释/ * ... * /。
特别是我需要在多行注释中找到PHP变量定义
例如:
/* other code $var = value1 */
$var = value2 ;
/*
other code
$var = value3 ;
other code
*/
必须只匹配评论中的两个'$ var =',而不是评论之外的那个。
对于上面的例子我写了一个使用无限制lookbehind的正则表达式,比如这个
(?<=[/][\*][^/]+)(\$var) | (?<=[/][\*][^\*]+)(\$var)
但是这个正则表达式失败,以防它找到charachter *和/即使它们是APART彼此之间,在注释开始标记'/ *'和$ var之间,这不是所需的行为:
例如它在这种情况下失败:
$var = .... ;
/*
other * code /
$var = .... ;
other code
*/
因为它找不到'*'和'/',即使它不是评论结束标记。
关键是我不能否定一个两个字符组合的标记,但只能一个一个地否定它们:[^ *]或[^ /]。
...此外,我不能使用令牌[\ s \ S]而不是[^ /]和[^ *],因为它会选择$ var,而不是前面的评论块。
有什么想法吗?是否可以通过正常的正则表达式实现这一目标?或者我需要不同的东西吗?
答案 0 :(得分:2)
这只与$var
匹配,并且只在多行注释中匹配:
(?s)\$var(?=(?:(?!/\*|\*/).)*\*/)
(?:(?!/\*|\*/).)*
是一个俘虏前瞻(也称为Tempered Greedy Token - 好名字,但音节太多),它是如何排除序列的,而不是单个字符。只要它不是(?s)
或/*
的第一个字符,就会匹配任何字符的零个或多个(包括换行符,因为*/
)。
如果在没有遇到*/
的情况下找到/*
,则封闭式前瞻会成功。这意味着当前位置必须在评论内(没有必要匹配开头/*
)。并且因为前瞻不会消耗任何字符,所以如果需要,您可以为每条评论匹配多个项目。
可以欺骗这个正则表达式的一件事是*/
并不是真正的评论。所以这些:
$var = "*/";
$var = ...;
// */
......即使他们不在评论中也会匹配。
答案 1 :(得分:1)
怎么样:
$str = '
/* other code */
$var = "var1";
/*
other code
$var = "var2";
other code
*/
/* other code */
$var = "var3";
/*
other code / <-- a slash here
$var = "var4";
other code
*/';
preg_match_all('~/\*(?:(?!\*/).)+?(\$var = .+?;).*?\*/~s', $str, $m);
print_r($m[1]);
<强>输出:强>
Array
(
[0] => $var = "var2";
[1] => $var = "var4";
)
答案 2 :(得分:1)
使用\G to glue匹配/*
(?:/\*|\G(?!^))(?:(?!\*/)[^$])*\K\$var\s*=\s*(?:(?!\*/)[^$;])*
如果你没有用正则表达式做很多事情,可能很难理解。 See regex101 for demo
\G
可以被视为&#34; glue&#34;,它会在上一场比赛结束时继续。但是\G
也匹配字符串的开头。这就是为什么使用负前瞻\G(?!^)
只需继续。
/\*|\G(?!^)
此部分用于在/*
找到匹配的开头或继续匹配。
(?:(?!\*/)[^$])*
匹配任何不是$
(否定类)的字符数,而不是(?!\*/)
之前/之间的内容$var
。 p>
\K\$var
\K
resets在$var
发生之前报告的匹配开始。 \K
可用作替代pcre中不可用的可变宽度lookebhind。
\s*=\s*(?:(?!\*/)[^$;])*
以匹配变量的值。这远非完美。如果quoted values或者不方便您输入,则需要修改。在=
之后,它与[^$;]
个字符匹配,这不是美元或分号(?!\*/)
只要前面没有*/
。
此正则表达式不会检查是否实际存在评论结束*/
它只是将匹配项绑定到/*
另一个想法是使用this trick种动词(*SKIP)(*FAIL)
,如in this demo。
答案 3 :(得分:0)
这样的事可能有用:
/\/\*.*?\$var\s*\=\s(.*?)(?=\s*;)/s
用法:
$str = '$var = .... ;
/*
other code
$var = ..... ;
other code
*/';
preg_match('/\/\*.*?\$var\s*\=\s(.*?)(?=\s*;)/s', $str, $matches);
var_dump($matches);
将输出:
array(2) {
[0]=>
string(26) "/*
other code
$var = ....."
[1]=>
string(5) "....."
}
您的字符串存储在$matches[1]