【问题标题】:Using regexp with etags to parse customized definitions使用带有 etags 的 regexp 来解析自定义定义
【发布时间】:2021-12-08 00:17:15
【问题描述】:

我有一个 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 文件。怎么了?

【问题讨论】:

    标签: regex perl exuberant-ctags


    【解决方案1】:

    Universal Ctags 刚刚引入了 pcre2 作为可选的正则表达式引擎。 如果您使用 pcre2 从 git 存储库 (git clone 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/\1/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/\1/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
    $
    

    【讨论】:

    • 我是从 github 构建的,但是没有 pcre2 支持:用你的命令检查。编译时如何开启?
    • pcre2 必须安装。 ctags 的源代码树中的配置脚本可能会检测到它。如果您遇到问题,请在 github.com/universal-ctags/ctags/issues 处提出问题。
    • 在 Ubuntu 上使用 pcre2 重建通用 ctags 后,您的正则表达式开始工作。
    • 现在我需要添加另一个正则表达式:->add_condition\(\s*['\''"]?(.*?)['\''"]?\s+=>\s*sub。是否可以为 Perl 创建一个文件,以便当 ctags 进行 Perl 解析时会使用多个正则表达式?
    • 将选项放到 ~/.ctags.d/myperl.ctags 中,例如 github.com/universal-ctags/ctags/blob/… 。注意:不需要为 shell 转义序列。
    【解决方案2】:

    您的问题之一是您的外壳转义,例如:

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

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

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

    那么单引号字符串就是:

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

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

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

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

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

    【讨论】:

    • 不幸的是,您的正则表达式出错:etags -l perl --regex='/\$app->helper\(['\''"](.*?)['\''"] => sub/' ./helpers.pl -> etags: Unmatched ( or \( while compiling pattern
    • etags 好像使用了 BRE 正则表达式?也许您可以指定一个标志来启用 ERE?否则,您需要提供 BRE 模式。 regular-expressions.info/posix.html
    • 好的,我试过通用 ctags,但 TAGS 文件还是空的:/usr/local/bin/ctags --langmap=perl:.pm.pl --languages=perl --regex-perl='/\$app->helper\(['\''"](.*)['\''"] => sub/\1/' ./helpers.pl
    • 在 Universal Ctags 中添加 -e 选项生成 TAGS 输出。
    • 将包含非贪婪修饰符的 pcre2 引入 Universal Ctags 正在进行中。见github.com/universal-ctags/ctags/pull/3036
    猜你喜欢
    • 2020-09-15
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2012-01-21
    • 1970-01-01
    • 2012-12-07
    相关资源
    最近更新 更多