我有一个正则表达式来查找文件中的函数。
查看表达式如何在PHP 中完美工作
如果我试图从控制台用grep运行相同的regex,我会得到一个错误:
grep -rP "(_t's*'('s*(['''"])('d+)'2's*,'s*(['''"])(.*?)(?<!'')'4's*(?(?=,)[^')]*'s*')|')))" application scripts library public data | sort -n | uniq
grep: unrecognized character after (?<
看起来grep
无法处理正则表达式(?<!'')
的这一部分,这对我来说很重要
有人能建议如何修改regex以使grep
能够使用它吗?
编辑:字符串:_t('123', 'pcs.', '', $userLang) . $data['ticker'] . ' (' . $data['security_name'] . ')
需要查找:
函数中的索引(123')
功能中的文本('cs.')
功能本身
> _t('123', 'pcs.', '', $userLang)
按照我在评论中所说的去做可以解决你的问题(使用链接中的数据):
$ cat file
_t('123', 'шт.', '', $userLang) . $data['ticker'] . ' (' . $data['security_name'] . ')
$ grep -P '(_t's*'('s*(['"'"'"])('d+)'2's*,'s*(['"'"'"])(.*?)(?<!'')'4's*(?(?=,)[^')]*'s*')|')))' file
_t('123', 'шт.', '', $userLang) . $data['ticker'] . ' (' . $data['security_name'] . ')
这里的技巧是在整个正则表达式周围使用单引号,然后每当你想要一个单引号时,就执行'"'"'
,这意味着"关闭原始字符串,在双引号中添加一个单括号,然后打开一个新的单引号字符串"。glglgl提出的另一种选择是使用''''
,即关闭原始字符串,添加转义的'
并打开新字符串。
使用单引号可以防止bash将!
解释为历史扩展。正如gniourf_gniourf上面提到的,另一种选择是使用set +o history
禁用该行为。
作为一个建议,如果您希望捕获regex的单独部分(并且您已经在grep中使用PCRE模式),则可以使用Perl:
$ perl -lne '/(_t's*'('s*([''''"])('d+)'2's*,'s*([''''"])(.*?)(?<!'')'4's*(?(?=,)[^')]*'s*')|')))/ && print "group 1: $1'ngroup 3: $3'n group 5: $5"' file
group 1: _t('123', 'шт.', '', $userLang)
group 3: 123
group 5: шт.
我强烈建议使用标记化器扩展来解析PHP文件。这是因为解析编程语言需要一个有状态的解析器,单个正则表达式是无状态的,因此无法提供这一点。
下面是一个如何从PHP源文件中提取函数名的示例,跟踪函数调用也是可能的:
$source = file_get_contents('some.php');
$tokens = token_get_all($source);
for($i = 0; $i < count($tokens); $i++) {
$token = $tokens[$i];
if(!is_string($token)) {
if($token[0] === T_FUNCTION) {
// skip whitespace between the keyword 'function'
// and the function's name
$i+=2;
// Avoid to print the opening brackets of a closure
if($tokens[$i][0] === T_STRING) {
echo $tokens[$i][1] . PHP_EOL;
}
}
}
}
在评论中,您告知您还想解析html、js文件。我建议使用DOM/JS解析器。