正则表达式/(ab)?使用/:更复杂的表达值得吗?

时间:2011-07-07 16:50:34

标签: regex perl

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

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

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

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

然而我意识到,使用那个正则表达式可能对我应该做的任务来说是“过度杀伤”......可能是模式

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

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

非常感谢。

4 个答案:

答案 0 :(得分:22)

除非您使用的是早于5.10的perl,否则简单的更改无论如何都会表现得更好(请参阅here),因此没有理由尝试对其进行优化。

答案 1 :(得分:5)

不是将助记符放在正则表达式中,而是使用哈希构建调度表。它将至少同样更快,您的代码更容易遵循:

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?...
}

答案 2 :(得分:5)

我喜欢salva's dispatch table(我在掌握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建议的操作码,但也可以进行更改。正如你所指出的,无论如何你现在可以免费使用Perl。

答案 3 :(得分:4)

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

是的,这太过分了。