2016-11-24 3 views
2

Я пытаюсь разобрать файл csv, и я пытаюсь получить доступ к регулярному выражению имен в proto regex в Perl6. Оказывается, это Нил. Каков правильный способ сделать это?Как получить доступ к захватам в матче?

grammar rsCSV { 
    regex TOP { (\s* <oneCSV> \s* \, \s*)* } 
    proto regex oneCSV {*} 
      regex oneCSV:sym<noQuote> { <-[\"]>*? } 
      regex oneCSV:sym<quoted> { \" .*? \" } # use non-greedy match 
} 

my $input = prompt("Enter csv line: "); 

my $m1 = rsCSV.parse($input); 
say "==========================="; 
say $m1; 
say "==========================="; 
say "1 " ~ $m1<oneCSV><quoted>; # this fails; it is "Nil" 
say "2 " ~ $m1[0]; 
say "3 " ~ $m1[0][2]; 

спасибо!

lisprog

ответ

3

Подробного обсуждение дополнения ответа Кристоф

Я пытаюсь разобрать CSV-файл

Возможно, вы сосредоточены на изучение Perl 6 синтаксических и писать некоторые одноразовый код. Но если вы хотите, чтобы промышленная прочность CSV разбиралась из коробки, обратите внимание на модули Text :: CSV [1].

Я пытаюсь получить доступ к именованному REGEX

Если вы изучаете Perl 6 синтаксические, пожалуйста, быть в курсе грамматике трассирующего и отладчик jnthn в [2].

в прото регулярном выражении в Perl6

Ваш вопрос не имеет никакого отношения к этому является прото регулярным выражением.

Вместо этого проблема в том, что, в то время как объект матча, соответствующий ваше имя захват является хранится в общем объекте матча хранящегося в $m1, он не хранится именно там, где вы ищете его.

Где отображаются объекты, соответствующие захватам?

Чтобы узнать, что происходит, я начну с моделирования того, что вы пытаетесь сделать. Я буду использовать регулярное выражение, которое объявит только один захват, «названный» (он же «Ассоциативный») захват, который соответствует строке ab.

given 'ab' 
{ 
    my $m1 = m/ $<named-capture> = (ab) /; 

    say $m1<named-capture>; 
    # 「ab」 
} 

Объект матч, соответствующий имени захвата хранится где вы, вероятно ожидать, что она появится в $m1, в $m1<named-capture>.

Но вы получали Nil с $m1<oneCSV>. Что дает?

Почему ваш $m1<oneCSV> не работает

Есть два типа захвата: по имени (так называемый «Ассоциативный») и нумерованных (ака «Позиционные»). В круглых скобках вы написали в своем регулярном выражении, окружавшей <oneCSV> введены пронумерованных захвата:

given 'ab' 
{ 
    my $m1 = m/ ($<named-capture> = (ab)) /; # extra parens added 

    say $m1[0]<named-capture>; 
    # 「ab」 
} 

В круглых скобках в / (...) / объявить один верхний уровень пронумерованного захват. Если он совпадает, соответствующий объект соответствия сохраняется в $m1[0]. (Если регулярное выражение выглядело / ... (...) ... (...) ... (...) ... / то другой объект матча, соответствующий тому, что соответствует второй паре скобок будет храниться в $m1[1], другой в $m1[2] для третьего, и так далее.)

Результат матча для $<named-capture> = (ab) затем сохраняются внутри$m1[0]. Вот почему работает say $m1[0]<named-capture>.

Пока все хорошо. Но это только половина истории ...

Почему $m1[0]<oneCSV> в коде не будет работать либо

Хотя $m1[0]<named-capture> в непосредственно выше код работает, вы еще не получить объект матча в $m1[0]<oneCSV> в ваш исходный код. Это потому, что вы попросили нескольких матчей захвата нулевого, потому что вы использовали *quantifier:

given 'ab' 
{ 
    my $m1 = m/ ($<named-capture> = (ab))* /; # * is a quantifier 

    say $m1[0][0]<named-capture>; 
    # 「ab」 
} 

Поскольку * квантора просит для нескольких матчей, Perl 6 пишет список матча объектов в $m1[0] , (В данном случае есть только один такой матч, так что вы в конечном итоге со списком длины 1, то есть только $m1[0][0] (и не $m1[0][1], $m1[0][2] и т.д.).)

Резюме

  • захватывает гнездо;

  • захват количественно либо * или + соответствует два уровней вложенности не только один.

  • В вашем исходном коде вам нужно будет написать say $m1[0][0]<oneCSV>;, чтобы добраться до объекта матча, который вы ищете.


[1] Установите соответствующие модули и писать use Text::CSV; (для чистой реализации Perl 6) или use Text::CSV:from<Perl5>; (для осуществления Perl 5 плюс XS) в начале вашего кода. (talk slides (нажмите на верхнее слово, например «csv», для продвижения по слайдам), video, Perl 6 module, Perl 5 XS module.)

[2] Установите соответствующие модули и напишите use Grammar::Tracer; или use Grammar::Debugger; в начале вашего кода`. (talk slides, video, modules.)

+1

Большое вам спасибо, raiph !!! Теперь я вижу свои проблемы после вашего подробного объяснения. Большое вам спасибо за ваше время !!! – lisprogtor

+0

@lisprogtor Добро пожаловать. Если вы можете сказать мне, какой конкретный бит был/был наиболее полезным для вас, это было бы особенно полезно для меня. :) – raiph

+1

Спасибо raiph. Это ваше объяснение ассоциации между деревом объектов named/numbered capture и match и тем фактом, что с *, perl6 создает список вместо одного объекта. Еще раз спасибо! – lisprogtor

2

Матч за <oneCSV> жизни в пределах объема группы захвата, которую вы можете получить с помощью $m1[0].

Поскольку группа определяется количественно с помощью *, результаты снова будут списком, то есть вам нужна другая операция индексирования, чтобы получить объект соответствия, например $m1[0][0] для первого.

Именованный захват может быть доступен по имени, например $m1[0][0]<oneCSV>. Это уже будет содержать результат совпадения соответствующей ветви проторегекса.

Если вы хотите, чтобы весь список совпадений вместо определенного, вы можете использовать >> или map, например $m1[0]>>.<oneCSV>.

+0

Спасибо Кристоф. Мое понимание Perl 6 было поддержано вашими ответами! – lisprogtor

Смежные вопросы