使用带有 etags 的正则表达式来解析自定义定义

Using regexp with etags to parse customized definitions

我有一个 perl 文件,其中一些函数是使用特殊语法 (Mojolicious) 定义的:

$app->helper('helper1' => sub {
            print "Hello 1";
        });

$app->helper("helper2" => sub {
            print "Hello 2";
        });

$app->helper(helper3 => sub {
            print "Hello 3";
        });

helper1();
helper2();
helper3();

我设法创建了 Perl 正则表达式来捕获这些定义:

#!/usr/bin/perl

use strict;
use warnings;
use File::Slurp 'read_file';

my $code = read_file('helpers.pl');

my @matches = $code =~ /$app\->helper\(['"]?(.*?)['"]? => sub/g;
foreach(@matches)
{
    print "$_\n";
}

输出:

helper1
helper2
helper3

但是我尝试在 etags 中使用它失败了;

etags -l perl --regex="/$app\->helper\\(['\"]\(.*?\)['\"] => sub/" ./helpers.pl

给出一个空的 TAGS 文件。怎么了?

你的问题之一是你的 shell 转义,例如:

  • "$xxx" 最终会变成 $xxx,这意味着正则表达式中的 EOL。
  • "\-" 将在 POSIX shell 中扩展为 \-.

您应该使用单引号字符串来保存您的模式,因为单引号中唯一的特殊字符是单引号。如果模式应该是:

/$app->helper\(['"](.*?)['"] => sub/

那么单引号字符串将是:

'/$app->helper\(['\''"](.*?)['\''"] => sub/'

我不使用 exuberant-ctags,但从不使用 Universal Ctags。在 Universal Ctags 中需要这样写:

/$app->helper\(['"](.*)['"] => sub//

请注意如何不支持非贪婪修饰符,以及我如何提供关键字创建部分:/ 在模式之后。

我将把它作为 reader 的练习留给上面的模式用单引号引起来。

Universal Ctags 刚刚引入了 pcre2 作为可选的正则表达式引擎。 如果您使用 pcre2 从 git 存储库(git 克隆 https://github.com/universal-ctags/ctags.git)中的最新代码构建 ctags 可执行文件,则可以使用非贪婪匹配。这意味着 Andreas Louv 显示的命令行可能运行良好。

$ cat /tmp/foo.pl                                                                                                                                                                             
$app->helper('helper1' => sub {                                                                                                                                                               
            print "Hello 1";                                                                                                                                                                  
        });                                                                                                                                                                                   
                                                                                                                                                                                              
$app->helper("helper2" => sub {                                                                                                                                                               
            print "Hello 2";                                                                                                                                                                  
        });                                                                                                                                                                                   
                                                                                                                                                                                              
$app->helper(helper3 => sub {                                                                                                                                                                 
            print "Hello 3";                                                                                                                                                                  
        });                                                                                                                                                                                   
                                                                                                                                                                                              
helper1();                                                                                                                                                                                    
helper2();                                                                                                                                                                                    
helper3();                                                                                                                                                                                    
                                                                                                                                                                                              
$ ./ctags -o - --regex-perl='/$app->helper\(['\''"]?(.*?)['\''"]? => sub//s/{pcre2}' /tmp/foo.pl                                                                                           
helper1 /tmp/foo.pl     /^$app->helper('helper1' => sub {$/;"   s                                                                                                                             
helper2 /tmp/foo.pl     /^$app->helper("helper2" => sub {$/;"   s                                                                                                                             
helper3 /tmp/foo.pl     /^$app->helper(helper3 => sub {$/;"     s                                                                                                                             
$ ./ctags -e --regex-perl='/$app->helper\(['\''"]?(.*?)['\''"]? => sub//s/{pcre2}' /tmp/foo.pl                                                                                             
$ cat TAGS                                                                                                                                                                                    
^L                                                                                                                                                                                            
/tmp/foo.pl,133                                                                                                                                                                               
$app->helper('helper1' => sub {^?helper1^A1,0                                                                                                                                                 
$app->helper("helper2" => sub {^?helper2^A5,74                                                                                                                                                
$app->helper(helper3 => sub {^?helper3^A9,148                                                                                                                                                 
$                                                                                             

您可以验证 pcre2 是否链接到您的 ctags。

$ ./ctags --list-features | grep pcre2
pcre2             has pcre2 regex engine
$