понедельник, 28 декабря 2009 г.

PREG_OFFSET_CAPTURE in Perl

Портирую одну вещь с PHP на Perl.

php -r'preg_match("/(\w+).*?(\w+)/","Hello, world!",$m,PREG_OFFSET_CAPTURE);var_export($m);'
perl -MData::Dumper -e'"Hello, world!"=~/(\w+).*?(\w+)/p;print Dumper[map[$_?$$_:${^MATCH},$-[$_]],0..$#-];'

No comments.

Update: и еще короче! (с подачи zloy-russkiy)

perl -MData::Dumper -E'say Dumper[map[$_,$-[$}++]],${^MATCH},"Hello, world!"=~/(\w+).*?(\w+)/p];'

13 comments:

  1. не хватает версии перла.
    может substr($s, $-[$_], $+[$_] - $-[$_])?
    ОтветитьУдалить
  2. На моей машине версии перла вполне хватает B-) Хотя с целью большей переносимости в том коде, который я портирую, написал именно так, как Вы сказали. Здесь же я показал другой способ не в последнюю очередь с умыслом на то, чтобы напомнить коллегам о новой фиче в 5.010.

    P. S. Ну вот, блин, опять без комментов не получилось ;-(
    ОтветитьУдалить
  3. Сурово =)
    Я сам попробовал у меня получилось менее компактно, но более разборчиво.
    ОтветитьУдалить
  4. perl -MData::Dumper -E 'say Dumper \map {[ $_, $-[++$i] ]} "Hello, world!" =~ /(\w+).*?(\w+)/;'
    ОтветитьУдалить
  5. Это не то же самое. Во-первых, $m[0] в PHP относится ко всему совпадению целиком, во-вторых, Ваш код возвращает список ссылок на ссылку на массив вместо ссылку на массив ссылок на массив :-) Второе решается просто заменой '\' на '[]'. С первым сложнее.
    ОтветитьУдалить
  6. Точно! Ну первое требование тоже очень просто решается:

    меняем увеличение $i на постфиксную форму + добавляем $^{MATCH} (я умело подглядел это выше =) ) + модификатор p к регулярному выражению (собственно тоже подглядел, спасибо за это) + обрамление []

    perl -MData::Dumper -E 'say Dumper [map {[ $_, $-[$i++] ]} ${^MATCH},"Hello, world!" =~ /(\w+).*?(\w+)/p];'

    TMTOWTDI =)
    ОтветитьУдалить
  7. Ага, уже писал тот же код. Вы оказались проворнее :-)
    ОтветитьУдалить
  8. ещё вариант навеяло:

    perl -MMoose::Autobox -E 'say [ ${^MATCH},"Hello, world!" =~ /(\w+).*?(\w+)/p ]->map(sub { [ $_,$-[$i++] ] })->dump'
    ОтветитьУдалить
  9. Такой вариант, конечно, изощренней, но других преимуществ в нем не вижу :-)
    ОтветитьУдалить
  10. Ну он более литературный, так сказать, слева направо читается =)
    ОтветитьУдалить
  11. > слева направо читается

    А у Вас точно лево и право с той же стороны, что и у меня? :-)
    ОтветитьУдалить
  12. Ну вроде бы на месте было утром, а что не так? =)
    ОтветитьУдалить
  13. Да просто мне первый вариант читать как-то привычнее :-)
    ОтветитьУдалить