Почему Regexp :: Assemble терпит неудачу с этими простыми регулярными выражениями? - PullRequest
1 голос
/ 16 ноября 2009

Я использую Regexp :: Assemble в моем проекте, но я не понимаю, почему этот маленький пример не работает:

#!/usr/bin/perl

use strict;
use warnings;

use Regexp::Assemble;

my $re1 = "(run (?:pre|post)flight script for .+)";
my $re2 = "((?:Configu|Prepa)ring volume .+)";

my $ra   = Regexp::Assemble->new;
$ra->add($re1);
$ra->add($re2);
my $global = $ra->re;

print "GLOBAL: $global\n";

1;

Я получил эту ошибку:

Unmatched ( in regex; marked by <-- HERE in m/( <-- HERE ?:(run (?:pre|post)flight script for|((?:Configu|Prepa)ring volume) .+)/ at /usr/share/perl5/Regexp/Assemble.pm line 1003.

Edit: Если я просто распечатаю полученное регулярное выражение ($ ra-> as_string), я получу это:

GLOBAL: (?:(run (?:pre|post)flight script for|((?:Configu|Prepa)ring volume) .+)

Один ')' отсутствует ...

Ответы [ 3 ]

4 голосов
/ 16 ноября 2009

Подход Ether выглядит как план - если вы посмотрите на документацию модуля, он упоминает специально для наблюдения:

add() ... Он использует наивное регулярное выражение, чтобы передать строку, которая может быть одурачена [сложными] выражениями (в частности, он не сможет передать вложенные выражения в скобках, например, ab (cd (ef) ? gh) я правильно). В этом случае конец строки не будет правильно помечен и возвращен как одна длинная строка.

4 голосов
/ 17 ноября 2009

Я автор R :: A. Этот вопрос возникает каждые пару лет. Идея состоит в том, что вы не хотите добавлять сложные шаблоны, заключенные в скобки. Добавьте больше, более простых образцов, например

run preflight script for .+
run postflight script for .+
Configuring volume .+
Preparing volume .+

Не пытайтесь выполнить работу модуля. Например, ваша преждевременная группировка привела к тому, что конечный .+, общий для всех шаблонов, не учитывается ни в одном случае в регулярном выражении. В результате вы ввели ненужный возврат. Чем больше шаблонов вы добавите, тем хуже будет.

Вызов add () в другом порядке приведет к тому же самому полученному шаблону (иначе я хотел бы знать об ошибке).

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

2 голосов
/ 16 ноября 2009

Это похоже на ошибку? Вы путаете конструктор регулярных выражений. Посмотрите, как он объединил два ваших шаблона и не соответствует скобкам:

my $re1 =     "(run (?:pre|post)flight script for .+)";
my $re2 =                                        "((?:Configu|Prepa)ring volume .+)";

#         m/(?:(run (?:pre|post)flight script for|((?:Configu|Prepa)ring volume) .+)/ at...

Попробуйте удалить лишние скобки из регулярных выражений и посмотрите, поможет ли это:

my $re1 = "run (?:pre|post)flight script for .+";
my $re2 = "(?:Configu|Prepa)ring volume .+";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...