【问题标题】:Regular expression /(ab)?use/: Is a more complex expression worth it?正则表达式 /(ab)?use/:更复杂的表达式值得吗?
【发布时间】:2011-07-09 06:55:06
【问题描述】:

我正在编写一个简单的 Perl 脚本,将汇编指令字符串转换为 32 位二进制代码。

我决定按类型处理翻译分组指令(ADDSUB 是 R-Type 指令等等......)所以在我的代码中我正在做这样的事情:

my $bin = &r_type($instruction) if $instruction =~ /^(?:add|s(?:ub|lt|gt))\s/;

因为我想以同样的方式处理addsubsltsgt

但我意识到,对于我应该做的任务来说,使用该正则表达式可能是“矫枉过正”……模式可以吗

/^(?:add|sub|slt|sgt)\s/

表示在这种情况下更好地使用正则表达式?

非常感谢。

【问题讨论】:

  • 在这种情况下,列出操作码更便于阅读。使用交替。

标签: regex perl


【解决方案1】:

除非您使用的是 5.10 之前的 perl,否则简单的替换将执行得更好(请参阅 here),因此没有理由尝试对其进行优化。

【讨论】:

    【解决方案2】:

    不要将助记符埋在正则表达式中,而是使用散列构建一个调度表。它至少会更快,并且您的代码更容易遵循:

    my %emitter = (add => \&r_type,
                   sub => \&r_type,
                   slt => \&r_type,
                   sgt => \&r_type,
                   ...);
    
    if ($instruction =~ /^(\S+)/) {
        my $emitter = $emitter{$1} // die "bad instruction $instruction";
        $emitter->($1, $istruction);
    }
    else {
        # error?...
    }
    

    【讨论】:

    • 非常好的方法!谢谢你的建议:)
    【解决方案3】:

    我喜欢 salva's dispatch table(我在 Mastering Perl 中展示了很多),但我会回答这个问题的另一个方面,以防有一天你需要这个答案来解决不同的问题。

    当您想要构建一些交替时,其中一些可能是嵌套的,您可以使用类似Regexp::Trie 的东西来为您构建交替,这样您就不会看到丑陋的正则表达式语法:

    use Regexp::Trie;
    my $rt = Regexp::Trie->new;
    
    foreach ( qw/add sub slt sgt/ ) {
        $rt->add($_);
        }
    
    print $rt->regexp, "\n";
    

    这给了你:

     (?-xism:(?:add|s(?:gt|lt|ub)))
    

    这样,您可以像 Jonathan 建议的那样列出操作码,但也可以得到交替。正如 ysth 所说,无论如何你现在都可以通过 Perl 免费获得这个。

    【讨论】:

    • 非常感谢,我会记住的! (……发现我的暑期读物……;))
    【解决方案4】:

    您的第二个版本更简单、更易读、更易于维护。性能差异将取决于正则表达式的实现,但我怀疑嵌套版本会由于其复杂性增加而运行得更慢。

    是的,这太过分了。

    【讨论】:

      猜你喜欢
      • 2018-08-06
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多