Как я могу избежать подобных коду вещей в строке Perl?

$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++;
}

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

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

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

Спасибо.


person xain    schedule 24.02.2010    source источник
comment
Я не знаю, что это такое, но это точно не Perl.   -  person friedo    schedule 24.02.2010
comment
Код внутри print/EOT конечно нет, но это не главное, мне просто нужно, чтобы то, что находится внутри print/EOT, было записано в stdout; на самом деле, если я удаляю блок if, он работает отлично.   -  person xain    schedule 24.02.2010
comment
Doh -- я пропустил тот факт, что материал был в большой heredoc.   -  person friedo    schedule 24.02.2010


Ответы (5)


Трудно сказать, что должен делать этот код, но, может быть, вы хотите, чтобы внешние знаки доллара в операторе 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"
}
person Sean    schedule 24.02.2010
comment
Код является частью более крупного скрипта, который загружает cvs и создает отличные классы из его данных. Вопрос в том, почему компилятор perl пытается скомпилировать блок внутри print/EOT и как запретить это делать (кстати, спасибо за рекомендацию, но это не сработало) - person xain; 24.02.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.

person rjh    schedule 24.02.2010

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

println "${"px$i.name"} / ${"px$i.empr.to"} OK"
println "px$i.name" / px$i.empr.to OK"
person Brad Gilbert    schedule 24.02.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. в разделе «Кровавые подробности разбора цитируемых конструкций».

person Ether    schedule 24.02.2010

person    schedule
comment
(+1) существует несколько видов одинарных кавычек heredocs, которые не интерполируются. другой тип - обратные кавычки, например. EOT, который будет выполнять строку через оболочку. - person harschware; 25.02.2010