Могу ли я заменить оператор связывания на оператор smartmatch в Perl? - PullRequest
2 голосов
/ 28 октября 2009

Как я могу написать это с помощью оператора smartmatch (~~)?

use 5.010;

my $string = '12 23 34 45 5464 46';

while ( $string =~ /(\d\d)\s/g ) {
    say $1;
}

Ответы [ 4 ]

4 голосов
/ 28 октября 2009

Интересно. perlsyn состояния:

Любой ~~ Соответствие регулярному выражению $a =~ /$b/

так что, на первый взгляд, разумно ожидать

use strict; use warnings;
use 5.010;

my $string = '12 23 34 45 5464 46';

while ( $string ~~ /(\d\d)\s/g ) {
    say $1;
}

для печати 12, 23 и т. Д., Но он застревает в цикле, повторяя 12. Использование:

$ perl -MO=Deparse y.pl

выходы

while ($string ~~ qr/(\d\d)\s/g) {
    say $1;
}

глядя на perlop , мы замечаем

qr/STRING/msixpo 

Обратите внимание, что 'g' не указан в качестве модификатора (логично, для меня).

Интересно, если вы напишите:

my $re = qr/(\d\d)\s/g;

perl barfs:

Bareword found where operator expected at C:\Temp\y.pl line 5, 
near "qr/(\d\d)\s/g"
syntax error at C:\Temp\y.pl line 5, near "qr/(\d\d)\s/g"

и, вероятно, он также должен что-то сказать, если в приведенном выше коде используется недопустимое выражение

1 голос
/ 29 октября 2009

Если мы посмотрим, во что превращаются эти два варианта, мы увидим причину этого.


  • Сначала давайте посмотрим на оригинальную версию.

    perl -MO=Deparse -e'while("abc" =~ /(.)/g){print "hi\n"}'
    
    while ('abc' =~ /(.)/g) {
        print "hi\n";
    }
    

    Как видите, никаких изменений кодов операций не было.

  • Теперь, если вы перейдете и измените его на использование оператора smart-match, вы увидите, что он действительно изменится.

    perl -MO=Deparse -e'while("abc" ~~ /(.)/g){print "hi\n"}'
    
    while ('abc' ~~ qr/(.)/g) {
        print "hi\n";
    }
    

    Изменяет его на qr, который не распознает опцию /g.

    Это, вероятно, должно дать вам ошибку, но она не преобразуется, пока не будет проанализирована.


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

    syntax error at -e line 1, near "qr/(.)/g"


Функция smart-match никогда не предназначалась для замены оператора =~. Он вышел из процесса заставить given / when работать так, как он работает.

В большинстве случаев when(EXPR) рассматривается как неявное интеллектуальное совпадение из $_.
...

0 голосов
/ 29 октября 2009

Если честно, я не уверен, что для этого вы можете использовать оператор интеллектуального соответствия. В моем ограниченном тестировании похоже, что интеллектуальное совпадение возвращает логическое значение вместо списка совпадений. Однако код, который вы разместили (используя =~), может работать без него.
То, что вы опубликовали, не работает из-за цикла while. Условный оператор в цикле while выполняется перед началом каждой итерации. В этом случае ваше регулярное выражение возвращает первое значение в $string, потому что оно сбрасывается на каждой итерации. A foreach будет работать однако:

my $string = '12 23 34 45 5464 46';
foreach my $number ($string =~ /(\d\d)\s/g) {
    print $number."\n";
}
0 голосов
/ 29 октября 2009

Является ли ожидаемое поведение вывода первым бесконечным совпадением? Потому что это то, что этот код должен делать в своей текущей форме. Проблема не в операторе Smart-Match. Цикл while бесконечен, потому что модификация $string никогда не происходит. Глобальный переключатель /g не меняет сам цикл.

Чего ты пытаешься достичь? Я предполагаю, что вы хотите вывести двузначные значения, по одному на строку. В этом случае вы можете рассмотреть:

say join("\n", grep { /^\d{2}$/ } split(" ",$string));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...