为什么grep不能处理正则表达式


Why grep is not working with regular expression?

我有一个正则表达式来查找文件中的函数。

查看表达式如何在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'] . ')

需要查找:

  1. 函数中的索引(123')

  2. 功能中的文本('cs.')

  3. 功能本身

    > _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解析器。