2010-02-24 6 views
5

$ i = 1; khi ($ i < 3) { in < < "EOT"; def px $ i = new E (người dùng) nếu (! Px $ i.hasErrors()) { println "$ {px $ i.name}/$ {px $ i.empr.to} OK" }Làm cách nào để thoát khỏi những thứ giống như mã trong chuỗi Perl?

EOT 

    $i++; 
} 

tạo ra lỗi:

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

Làm thế nào tôi có thể "thoát" nếu?

Cảm ơn.

+0

Tôi không biết đó là gì, nhưng chắc chắn không phải là Perl. – friedo

+0

Mã bên trong bản in/EOT chắc chắn không phải vậy, nhưng đó không phải là vấn đề, tôi chỉ cần những gì bên trong bản in/EOT được ghi vào stdout; trên thực tế, nếu tôi xóa khối "if", nó sẽ chạy hoàn hảo. – xain

+0

Doh - Tôi đã bỏ lỡ thực tế rằng các công cụ đã được trong một heredoc lớn. – friedo

Trả lời

6

Thật khó để nói mã này được cho là hoàn thành, nhưng có thể bạn muốn các dấu đô la bên ngoài trong câu lệnh println được giữ nguyên trong kết quả cuối cùng?

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

Với sự thay đổi đó, sản lượng lỗi tôi thấy là:

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

Mã này là một phần của tập lệnh lớn hơn tải một cv và tạo các lớp học hấp dẫn từ dữ liệu của nó.Câu hỏi đặt ra là tại sao trình biên dịch perl đang cố gắng biên dịch khối bên trong bản in/EOT và làm thế nào để nói nó không được. (BTW, cảm ơn lời khuyên nhưng nó không hoạt động) – xain

+0

@xain: Ý bạn là gì? "nó không hoạt động"? Hiển thị đầu ra chính xác bạn mong đợi để có được. Nó khác với sản lượng của Sean như thế nào? – toolic

+0

Sean, sai lầm của tôi. Nó hoạt động tốt. Cảm ơn! – xain

1

này cần khắc phục vấn đề.

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

Như bạn đã thấy, phần $px của chuỗi được đánh giá. Bạn chỉ cần thoát khỏi nó:

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

Đọc thêm về thoát chuỗi tại perldoc perlop trong "Chi tiết Gory phân tích cú pháp được trích dẫn".

4

Tùy chọn dòng lệnh -MO=Deparse cho bạn biết cách Perl đã giải thích mã của bạn sau khi đơn giản hóa nó (ví dụ: chuyển đổi heredocs thành qq {} khối). ví dụ.

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

Phần liên quan là:

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

Perl đã chuyển đổi ${px$i.name}-${$i->px . 'name'}!

Trong perl, ${...} có nghĩa là đánh giá mọi thứ nằm trong khối và coi nó là symbolic reference (ví dụ: tên biến) hoặc tham chiếu vô hướng, sau đó bỏ qua nó để biến nó trở thành vô hướng. Vì vậy, Perl cố gắng thực hiện bất cứ điều gì là bên trong các khối, xử lý nội dung của họ như là mã Perl. Điều này là do heredoc của bạn, "EOT" giống như một chuỗi được trích dẫn kép và nội suy các ký hiệu đô la.

Giải pháp là: thoát khỏi các ký hiệu đô la của bạn ($ ->\$) hoặc sử dụng dấu nháy đơn và nối hơn là 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) có nhiều loại trích dẫn đơn heredocs không được nội suy. một loại khác là backticks, ví dụ: 'EOT' sẽ thực hiện chuỗi thông qua trình bao. – harschware