2010-02-24 9 views
5

$ i = 1; natomiast ($ i < 3) { wydrukuj < < "EOT"; def px $ i = nowy E (użytkownik) if (! Px $ i.hasErrors()) { println "$ {px $ i.name}/$ {px $ i.empr.to} OK" }Jak można uciec przed kodami w łańcuchu Perla?

EOT 

    $i++; 
} 

produkuje błąd:

Can't call method "px" without a package or object reference at borrar.pl line 3.

Jak mogę "Escape" if?

Dzięki.

+0

Nie wiem, co to jest, ale na pewno nie jest to Perl. – friedo

+0

Kod wewnątrz print/EOT na pewno nie, ale nie o to chodzi, potrzebuję tylko tego, co jest w środku print/EOT do zapisania na stdout; w rzeczywistości, jeśli usunę blok "if", działa idealnie. – xain

+0

Doh - Tęskniłem za faktem, że materiał był w dużym heredoc. – friedo

Odpowiedz

6

Trudno powiedzieć, co ten kod ma osiągnąć, ale może chcesz, aby zewnętrzne znaki dolara w komunikacie println zostały zachowane w ostatecznym wyniku?

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

Z tej zmiany, wyjście bezbłędne widzę to:

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" 
} 
+0

Kod jest częścią większego skryptu, który ładuje CVS i tworzy groovy klasy z jego danych.Pytanie brzmi: Dlaczego kompilator perl próbuje skompilować blok wewnątrz wydruku/EOT i jak mu tego zabronić (BTW, dzięki za rekomendację, ale to nie zadziałało) – xain

+0

@xain: Co masz na myśli dokładnie przez "to nie zadziałało"? Pokaż dokładną wydajność, jakiej oczekujesz. Czym się różni od produkcji Seana? – toolic

+0

Sean, mój błąd. Wszystko działało dobrze. Dzięki! – xain

1

To powinno rozwiązać problem.

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

Jak widzieliście, część sznurka $px jest obliczana. Wystarczy go uniknąć:

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

Czytaj więcej o ciąg ucieczki na perldoc perlop pod „Gory szczegóły parsowania cytowany konstrukcje”.

4

Opcja wiersza poleceń -MO=Deparse pokazuje, jak Perl zinterpretował twój kod po jego uproszczeniu (np. Konwersję heredoc do qq {} bloków). na przykład

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

Odpowiedni fragment brzmi:

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

Perl został przekształcony ${px$i.name} do ${$i->px . 'name'}!

W języku Perl, ${...} oznacza ocenę tego, co znajduje się wewnątrz bloku, i traktuje to jako symbolic reference (tj. Nazwę zmiennej) lub odniesienie skalarne, a następnie usuwa je, aby przekształcić z powrotem w skalar. Tak więc Perl próbuje wykonać wszystko, co znajduje się wewnątrz tych bloków, traktując ich zawartość jako kod Perla. Dzieje się tak dlatego, że twój heredoc, "EOT" jest jak łańcuch podwójnie cytowany i interpoluje znaki dolara.

Rozwiązanie: uciec od znaków dolara ($ ->\$) lub użyć pojedynczych cudzysłowów i konkatenacji zamiast heredocs.

1
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

(+1) istnieje wiele rodzajów pojedynczych cudzysłowów heredocs, które nie są interpolowane. innym typem jest backtick, np. 'EOT', który wykonywałby łańcuch za pośrednictwem powłoki. – harschware

Powiązane problemy