我目前在特定情况下遇到了Regex的问题:我需要解析PHP源文件(尤其是类)以查找在这些文件中定义的常量并将它们检索回输出。
这些常量可以有一些文档(这就是为什么我离开了Reflection的想法,因为通过Reflection检索常量只返回它们的名称及其值),这些文档可能会在comments标记中提供。
我确实设法构建了正则表达式的两个独立部分(1是注释标记,另一个是const
声明)但我无法成功地将它们链接起来:它似乎文件中的第一个常量也将包含所有先前声明的元素,直到它到达第一个注释块。
我的正则表达式如下(我不是一个正则表达的上帝所以随时提出任何批评):
((\t\ )*(/\*+(.|\n)*\*/)\R+)?([\t| ]*(?|(public|protected|private)\s*)?const\s+([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*=\s*(.*);)
进行样本测试:Regex101
如果初始代码消失:
/**
*
*/
class Test {
/**
*
*/
public const LOL = "damn";
/**
*
*/
private const TEST = 5;
public const plop = "dong";
}
我确实在那里寻找提示并且我已经了解了正面的背后隐藏,但据我所知,它只适用于固定宽度的模式。
我的想法已经不多了。
答案 0 :(得分:1)
你可以在没有正面观察的情况下做到这一点: 你必须匹配一个注释,紧接着是一个const声明:
第一组将允许您检索文档:
(?:^/\*\*$\s+)
找到阻止评论的开头((?:^ ?\*.*$\s*?)+)
代表包含评论内容的小组(?:\s+^\*/$\s+)
评论结束^\s+
跳过行尾的空白(public|protected|private) const
确定可见性的小组(\S+)\s+= ([^;]+);
组的名称和值答案 1 :(得分:1)
我赞成采用多步骤方法:将每个类分开,然后寻找注释(最终)和常量。就正则表达而言,这可以通过
来实现class\h*(?P<classname>\w+)[^{}]* # look for class literally and capture the name
(\{
(?:[^{}]*|(?2))* # the whole block matches the class content
\})
<小时/>
现在,对于注释和常量
^\h*
(?:(?P<comment>\Q/*\E(?s:.*?)\Q*/\E)(?s:.*?))?
(?:public|private)\h*const\h*
(?P<key>\w+)\h*=\h*(?P<value>[^;]+)
同样请参阅a demo for this step on regex101.com。
<小时/> 最后一步是清理评论:
^\h*/?\*+\h*/?
查看cleansing on regex101.com的演示。
<小时/> 最后,您需要两个循环:
preg_match_all($regex_class, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
preg_match_all($const_class, $match[0], $constants, PREG_SET_ORDER);
foreach ($constants as $constant) {
$comment = preg_replace($clean_comment, '', $constant["comment"]);
# find the actual values here
echo "Class: {$match["classname"]}, Constant Name: {$constant["key"]}, Constant Value: {$constant["value"]}, Comment: $comment\n";
}
}
overall demo can be found on ideone.com
注意演示和源代码中的各个正则表达式修饰符(尤其是verbose
和multiline
!)。
$result = [];
preg_match_all($regex_class, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
preg_match_all($const_class, $match[0], $constants, PREG_SET_ORDER);
foreach ($constants as $constant) {
$comment = trim(preg_replace($clean_comment, '', $constant["comment"]));
$result[$match["classname"]][] = array('name' => $constant["key"], 'value' => $constant['value'], 'comment' => $comment);
}
}
print_r($result);