Регулярное выражение / (ab)? Use /: стоит ли более сложное выражение? - PullRequest
13 голосов
/ 07 июля 2011

Я пишу простой Perl-скрипт, который переводит строки инструкции по сборке в 32-битный двоичный код.

Я решил обработать инструкцию группировки переводов по типу (ADD и SUB являются инструкциями R-типа и так далее ...), поэтому в моем коде я делаю что-то вроде этого:

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

потому что я хочу обрабатывать add, sub, slt и sgt таким же образом.

Однако я понял, что, возможно, использование этого регулярного выражения может быть «излишним» для задачи, которую я должен выполнить ... может шаблон

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

представляет лучшее использование регулярных выражений в этом случае?

Большое спасибо.

Ответы [ 4 ]

22 голосов
/ 07 июля 2011

Если вы не используете Perl старше 5.10, простое чередование будет работать в любом случае лучше (см. здесь ), поэтому нет причин пытаться оптимизировать его.

5 голосов
/ 08 июля 2011

Мне нравится таблица диспетчеризации Сальвы (я многое показываю в Мастеринг 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)))

Таким образом, вы перечисляете коды операций, как предложил Джонатан, но также получаете чередование.Как уже отмечалось, вы можете получить это бесплатно с помощью Perl.

5 голосов
/ 07 июля 2011

Вместо того, чтобы размещать мнемонику, скрытую внутри регулярных выражений, создайте таблицу диспетчеризации, используя хэш. Это будет, по крайней мере, одинаково быстрее, и ваш код будет намного проще следовать:

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?...
}
4 голосов
/ 07 июля 2011

Ваша вторая версия проще, удобочитаемее и удобнее в обслуживании.Разница в производительности будет зависеть от реализации регулярных выражений, но я подозреваю, что вложенная версия будет работать медленнее из-за повышенной сложности.

Да, это излишне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...