2008-12-07 42 views
13

Tôi đã lập trình trong Perl, tắt và bật, trong nhiều năm nay, mặc dù chỉ thỉnh thoảng mới là ngôn ngữ chính của tôi. Bởi vì tôi thường đi nhiều tháng mà không viết bất kỳ perl nào, tôi dựa rất nhiều vào cuốn sách Camel Book tai chó của mình để nhắc tôi làm thế nào để làm việc. Tuy nhiên, khi tôi sao chép công thức nấu ăn nguyên văn mà không hiểu, điều này làm phiền tôi. Đây là một trong những khó khăn nhất: Trên trang 154 của 3rd edition Camel, có là một ví dụ cho "chuỗi sửa đổi en passant, mà đọc như thế này:Toán tử thay thế Perl hoạt động như thế nào?

($lotr = $hobbit) =~ s/Bilbo/Frodo/g; 

Q1) những gì đang xảy ra ở đây? Đây có phải là cú pháp gần như kỳ diệu cần thiết cho một thao tác cơ bản như "lấy một chuỗi từ $ a, sửa đổi nó bằng regex, đặt kết quả bằng $ b" không? Không.

Q3) Làm cách nào để thực hiện thao tác này bằng biến mặc định vòng lặp làm chuỗi ban đầu?

Lời xin lỗi trước những người mơ ước Perl mà người trên trông hoàn toàn tự nhiên.

Trả lời

22

Hmmm ... ($lotr=$hobbit) =~ s/Bilbo/Frodo/g là một trong nhiều ảo thuật của Perl. Bây giờ cho một số câu trả lời.

Q1) $lotr đang được chỉ định giá trị chứa trong $hobbit. Sau khi chuyển nhượng, chúng ta có thể quên biến nguồn. Hãy xử lý ($lotr = $hobbit) vì đó là tuyên bố của chính nó như thể chúng tôi đã viết:

$lotr = $hobbit; 
$lotr =~ s/Bilbo/Frodo/g; 

thay thế. Regex đang hoạt động trên $lotr.

Q2) Cú pháp chỉ đơn giản là phiên bản một dòng của đoạn mã được đưa ra ở trên. Nghĩ về nó như "sao chép chuỗi từ $a, sao chép nó vào $b, và sửa đổi $b với regex" thay vì "tham gia một chuỗi từ $a, sửa đổi nó với một regex, nơi kết quả trong $b"

Q3) Tôi giả sử rằng bạn có nghĩa là không gian tìm kiếm mẫu mặc định bằng "biến mặc định vòng lặp"? Trong trường hợp đó, chỉ cần sử dụng $_ thay vì $hobbit:

while (<>) { 
    chomp; 
    ($lotr = $_) =~ s/Bilbo/Frodo/g; 
    print "\$lotr = [$lotr]\n"; 
    print "\$_ = [$_]\n"; 
} 

Điều thú vị đủ, sự kỳ diệu var $_ không được sửa đổi bởi hoạt động này. Đây là cách bạn có thể kết luận rằng nhiệm vụ xảy ra trước thay thế regex và thay thế không tương tác trên không gian mẫu mặc định theo bất kỳ cách nào.

Và đối với những người lập trình Perl giàu kinh nghiệm ... Tôi không biết có quá nhiều người bị ném bởi một số cú pháp Perl bất kể họ đã nhìn chằm chằm vào nó bao nhiêu 'ông Schwartz dĩ nhiên;)

+0

Câu trả lời đó là chính xác. Tôi đã gõ nó như thế này đã được đăng. Nó (giải pháp) bằng cách này đã cho tôi một tìm kiếm Google để tìm kiếm. – Paul

+0

@ D.Shawley. Jees mate. Từ những gì bạn đã nói ở trên, tại sao $ _ sẽ được sửa đổi? "sao chép chuỗi từ $ a ($ _) ... vào $ b ($ lotr) và sửa đổi $ b ($ lotr) với regex, đặt kết quả bằng $ b ($ lotr)". Không có ma thuật nào liên quan đến $ _ cả. –

+0

Tôi bỏ phiếu cho điều này, là câu trả lời được chấp nhận. –

5

Các ngôn ngữ khác nhau làm những việc khác nhau với toán tử gán. Trong một số, nó là một tuyên bố, không phải là một biểu thức, vì vậy không thể được kết hợp thành một biểu thức lớn hơn. Trong một số, nó trả về giá trị được gán, nhưng chỉ là một giá trị (thường được gọi là một rvalue), không phải là một cái gì đó mà chính nó có thể được sửa đổi hoặc gán (một giá trị).Một ví dụ của việc này là C, nơi bạn có thể viết :

a = b = c; # assign value of c to b and a 

nhưng không:

++(b = a); # assign value of a to b, then increment b 

Và trong một số, kết quả của một bài tập là vế trái được gán cho. (Trong Perl, điều này chỉ áp dụng cho các phép gán vô hướng; danh sách gán là một con thú phức tạp hơn.) Vì vậy, bạn có thể làm ++ ($ b = $ a) hoặc ($ b = $ a) = ~ s/a/b/hoặc bất kỳ hoạt động nào khác mong đợi một giá trị trên bài tập, và trước tiên nó sẽ thực hiện nhiệm vụ và sau đó sửa đổi thêm lvalue được gán cho.

+0

Cảm ơn, thật tốt khi biết rằng cú pháp của ví dụ, trong khi không phải là phép thuật, là Perl cụ thể. –

1

Nếu trong Q2 bạn có nghĩa là để có một tiểu chuỗi từ $ a, bạn có thể thấy thành ngữ này hữu ích:

($b) = $a =~ /(substring-to-match)/; 
$b =~ s/regex-on-susbtring/result-string/; 

Cũng làm lưu ý rằng $ a và $ b không biến bình thường trong Perl vì chúng có các quy tắc phạm vi đặc biệt liên quan đến chức năng sắp xếp. Xem 'perldoc perlvar' để biết chi tiết.

Các vấn đề liên quan