我正在尝试用preg_match解析PHPDoc标签,但我遇到了一些负面的lookbehind问题。我之前从未使用过这些,但我的理解是它们被用作排除。
这是我的模式:
/\*\*.+?(?<! \*/)@access public.+? \*/\s+?function\s+[a-zA-Z0-9_]+\(
以下是我正在尝试解析的示例PHP文件:
<?php
/**
* This is the shortcut to DIRECTORY_SEPARATOR
*/
defined('DS') or define('DS',DIRECTORY_SEPARATOR);
/**
* Foo
*
* @return bool
* @access public
*/
function foo()
{
return true;
}
我希望将任何函数与@access公共标记匹配,但在这种情况下,匹配从DS常量的注释开始。我认为(?<! \*/)
会将其排除在与DS评论的结束评论标记匹配的位置。
我错过了什么?
答案 0 :(得分:2)
在@bishop的link之后,我发现了一个使用负向前瞻的例子,对我有用。
我改变了
.+?(?<! \*/)
到
(?:(?! \*/).)+?
现在完整的模式是:
/\*\*(?:(?! \*/).)+?@access public.+? \*/\s+?function\s+[a-zA-Z0-9_]+\(
编辑:
也匹配函数类型和参数的完整模式:
(?<full>[\t ]*?/\*\*(?:(?! \*/).)+?@access public(?:(?! \*/).)+? \*/\s+?(?:public |protected |private )??(?:static )??function\s+[a-zA-Z0-9_]+\(.*?\))
和班级匹配:
(?<full>(?<indent>[\t ]*?)/\*\*(?:(?! \*/).)+?@access public.+? \*/\s+?(?:abstract )??class\s+[a-zA-Z0-9_]+\s??.*?{)
答案 1 :(得分:0)
负面的后视必须是固定长度的。听起来使用某种DocBlock解析器会更好。有许多解决方案。
答案 2 :(得分:0)
使用token_get_all()
功能:
$tokens = token_get_all($code);
$result = array();
foreach ($tokens as $k=>$token) {
switch ($token[0]):
case T_DOC_COMMENT:
$isPublic = strpos($token[1], '@access public');
break;
case T_FUNCTION:
$isFunction = true;
break;
case T_WHITESPACE:
break;
case T_STRING:
if ($isFunction && $isPublic) $result[] = $token[1];
default:
$isFunction = false;
endswitch;
}
print_r($result);
为了了解您可以使用tokenizer提取的内容,我建议您将以下代码放在foreach循环中,endswitch;
下:
if ($isPublic && isset($token[1]))
printf("%s\t%s\t%s\n", $token[0],
token_name($token[0]),
strtr($token[1], "\n", ' ')
);