Как я могу избежать подобных вещей в строке Perl? - PullRequest
5 голосов
/ 24 февраля 2010

$ я = 1; while ($ i <3) { печать << "EOT"; def px $ i = new E (пользователь) if (! px $ i.hasErrors ()) { println "$ {px $ i.name} / $ {px $ i.empr.to} ОК" } </p>

EOT

    $i++;
}

выдает ошибку:

Невозможно вызвать метод "px" без ссылки на пакет или объект в строке 3. borrar.pl.

Как я могу "убежать" от if?

Спасибо.

Ответы [ 5 ]

6 голосов
/ 24 февраля 2010

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

println "\${px$i.name} / \${px$i.empr.to} OK"

С этим изменением безошибочный вывод, который я вижу:

def px1 = new E(user) 
if (!px1.hasErrors()) {
        println "${px1.name} / ${px1.empr.to} OK"
}

def px2 = new E(user) 
if (!px2.hasErrors()) {
        println "${px2.name} / ${px2.empr.to} OK"
}
4 голосов
/ 24 февраля 2010

Параметр командной строки -MO=Deparse показывает, как Perl интерпретировал ваш код после его упрощения (например, преобразование heredocs в блоки qq {}). например,

$ perl -MO=Deparse test.pl
$i = 1;
while ($i < 3) {
    print qq[    def px$i = new E(user) \n    if (!px$i.hasErrors()) {\n            println "${$i->px . 'name';} / ${$i->px . 'empr' . 'to';} OK"\n    }\n\n];
    ++$i;
}

Соответствующая часть:

println "${$i->px . 'name';} / ${$i->px . 'empr' . 'to';}

Perl конвертировал ${px$i.name} в ${$i->px . 'name'}!

В perl, ${...} означает оценку всего, что находится внутри блока, и обрабатывает его как символьную ссылку (т.е. имя переменной) или скалярную ссылку, а затем разыменовывает ее, чтобы превратить в скаляр Поэтому Perl пытается выполнить все, что находится внутри этих блоков, обрабатывая их содержимое как код Perl. Это потому, что ваш heredoc, "EOT" подобен строке в двойных кавычках и интерполирует знаки доллара.

Решение: избегайте знаков доллара ($ -> \$) или используйте одинарные кавычки и конкатенацию, а не heredocs.

1 голос
/ 25 февраля 2010
my $format = << 'EOT';
def px%d = new E(user)
    if (!px%d.hasErrors()) {
            println "${px%d.name} / ${px%d.empr.to} OK"
    }
EOT

for my $i ( 1 .. 3 ) {
    printf $format, ($i) x 4;
}
1 голос
/ 24 февраля 2010

Как вы видели, часть строки $px оценивается. Вам просто нужно избежать этого:

$i=1;
while($i<3) {
    print << "EOT";
    def px$i = new E(user) 
    if (!px$i.hasErrors()) {
            println "\${px$i.name} / \${px$i.empr.to} OK"
    }

EOT

    $i++;
}

Подробнее о экранировании строки в perldoc perlop в разделе "Gory details of синтаксический анализ цитируемых конструкций".

1 голос
/ 24 февраля 2010

Это должно решить проблему.

println "${"px$i.name"} / ${"px$i.empr.to"} OK"
println "px$i.name" / px$i.empr.to OK"
...