2013-08-07 36 views
6

Tôi đang làm việc thông qua một số mã Perl trong Yêu cầu Tracker 4.0 và đã gặp lỗi khi thông báo của người yêu cầu vé bị cắt. Tôi mới làm quen với Perl, tôi đã làm một số công việc với các biểu thức chính quy, nhưng tôi đang gặp một số rắc rối với điều này ngay cả sau khi đọc khá một chút.

tôi đã thu hẹp vấn đề của tôi xuống dòng mã này:

$content =~ s/\n-- \n.*?$//s 

tôi không hoàn toàn hiểu những gì nó đang làm và muốn có một lời giải thích tốt hơn.

Tôi hiểu rằng s/ / phù hợp với mẫu \n-- \n.*?$ và thay thế bằng không có gì.

Tôi không hiểu những gì .*?$ thực hiện. Dưới đây là sự hiểu biết cơ bản của tôi:

  • . là bất kỳ ký tự trừ \ n
  • * là 0 hoặc nhiều lần trong những nhân vật trước
  • ? là 0 hoặc 1 lần của nhân vật trước
  • $ là phần cuối của chuỗi

Sau đó, từ những gì tôi hiểu, số s cuối cùng làm cho . phù hợp với các dòng mới

Vì vậy, gần như, chúng tôi đang thay thế bất kỳ văn bản nào bắt đầu bằng \n-- \n - dòng mã này đang gây ra một số hành vi đáng ngờ mà tôi muốn được sắp xếp nếu ai đó có thể giải thích những gì đang xảy ra ở đây.

Ai đó có thể giải thích dòng này đang làm gì không? Có phải nó chỉ xóa tất cả văn bản sau \n-- \n đầu tiên hoặc có nhiều văn bản hơn không?

dài lê thê vấn đề phần/thực tế cuộc sống (bạn không cần phải đọc này để trả lời các câu hỏi)

vấn đề chính xác của tôi là nó đang cắt giảm các nội dung trích dẫn ở chữ ký.

Vì vậy, nếu email A từ một khách hàng nói:

gì đang xảy ra với thứ tự ABCD?
- Một số khách hàng

Câu trả lời nhân viên nói (lưu ý sự mất mát của chữ ký của khách hàng)

Nó được vận chuyển hiện nay

gì đang xảy ra với thứ tự ABCD?

Khách hàng trả lời

tôi đã không nhận được nó, nó đã không xuất xưởng !!!
- Một số khách hàng

Nó được vận chuyển hiện nay

gì đang xảy ra với thứ tự ABCD?

Khi chúng tôi trả lời, thông điệp của họ sẽ cắt giảm tại - mà giết chết tất cả các bối cảnh.

Nó xuất xưởng hiện nay, theo dõi số 12345

tôi đã không nhận được nó, nó đã không xuất xưởng !!!

Và dẫn đến việc nhiều hơn giải thích những gì tự nó là vv

Trả lời

8

Bạn đang gần như chính xác: nó loại bỏ tất cả mọi thứ từ sự xuất hiện cuối cùng của "\ n-- \ n" đến cùng . Điều này không loại bỏ tất cả mọi thứ từ lần xuất hiện đầu tiên là do nhà điều hành không tham lam ? - nó báo cho động cơ regex khớp với dạng có thể viết ngắn nhất của mẫu trước (.*).

Điều này thực hiện: Trong giao tiếp qua email, chữ ký thường tách biệt với nội dung thư theo đúng mẫu này: một dòng bao gồm chính xác hai dấu gạch ngang và dấu cách đơn. Vì vậy, những gì regex làm là loại bỏ tất cả mọi thứ bắt đầu với dấu phân cách chữ ký để kết thúc.

Bây giờ khách hàng của bạn làm gì (theo cách thủ công hoặc ứng dụng email khách của anh ấy) thêm câu trả lời được trích dẫn của email sau dấu phân cách chữ ký. Điều này rất bất thường: câu trả lời được trích dẫn phải được đặt trước công cụ sửa đổi chữ ký. Tôi không biết một ứng dụng email nào thực hiện mục đích này, nhưng có rất nhiều chương trình ở đó chỉ đơn giản là nhận email từ (từ các vấn đề về ký tự đối với việc trích dẫn SMTP không phù hợp, bạn có thể tạo ra một số lỗi đáng kinh ngạc) , vì vậy tôi sẽ không ngạc nhiên khi biết rằng thực sự có những khách hàng như vậy.

Một khả năng khác là đây là một ảnh hưởng của khách hàng - như ký tên riêng của mình sau --. Tuy nhiên, tôi nghi ngờ điều này không được thực hiện thủ công vì con người hiếm khi chèn một dấu cách sau hai dấu gạch ngang và sau đó là ngắt dòng.

+1

Thunderbird ít nhất cung cấp tùy chọn cho điều đó. Bạn có thể chọn đặt dấu ngoặc kép ở trên hoặc bên dưới chữ ký. Nó đủ thông minh để cắt phần '- \ n' khi trả lời, nhưng nó cũng tự cắt nó. Và Outlook không quan tâm đến dấu phân cách và sẽ luôn đặt dấu ngoặc kép bên dưới chữ ký (trong đó bạn sẽ phải tự đặt dấu phân tách). Trong TheBat! bạn đặt dấu ngoặc kép nơi bạn muốn chúng trong mẫu. – simbabque

2

Khi ? sau một lượng hóa (?, *, + hoặc {m,n}), nó đổi tham lam của lượng hóa mà [1]. Thông thường, các định lượng này khớp với nhiều ký tự nhất có thể, nhưng với ?, chúng khớp với số ít nhất.

say "Greedy:  ", "abc1234" =~ /\w(.*)\d/; 
say "Non-greedy: ", "abc1234" =~ /\w(.*?)\d/; 

Output:

bc123 
bc 

Vì có hai nơi $ thể phù hợp (trước một dòng mới trailing hoặc ở phần cuối của chuỗi), điều này có tác dụng sau:

$_ = "abc\n-- \ndef\n"; 
say "Greedy:  <<" . s/\n-- \n.*$//sr . ">>"; 
say "Non-greedy: <<" . s/\n-- \n.*?$//sr . ">>"; 

Đầu ra:

Greedy:  <<abc>> 
Non-greedy: <<abc 
>> 

Nó đảm bảo dòng mới chấm dứt dòng cuối cùng không bị xóa. Sau đây là tương đương đơn giản hơn:

s/\n-- \n.*/\n/s 

s/(?<=\n)-- \n.*//s # Slow 

s/\n\K-- \n.*//s  # Requires 5.10 

Lưu ý rằng nó sẽ loại bỏ bắt đầu với -- đầu tiên.

$ perl -E'say "abc\n-- \ndef\n-- \nghi\n" =~ s/\n-- \n.*?$//sr' 
abc 

Nếu bạn muốn bắt đầu loại bỏ từ cuối cùng, bạn sẽ phải thay thế .* với một cái gì đó bảo đảm không phù hợp --.

$ perl -E'say "abc\n-- \ndef\n-- \nghi\n" =~ s/\n-- \n(?:(?!-- \n).)*?$//sr' 
abc 
-- 
def 

Ghi chú:

  1. Nó cũng có ý nghĩa tương tự nếu nó sau một modifier lượng hóa (ví dụ /.*+?/).
+0

@candyman, Đã cập nhật – ikegami

1

Có một mô-đun CPAN đẹp có thể giúp bạn hiểu được biểu thức thông thường trong tương lai: YAPE::Regex::Explain

Bạn có thể tìm thấy một phiên bản trực tuyến của nó ở đây: http://rick.measham.id.au/paste/explain.pl

Chạy regex của bạn thông qua lợi nhuận website như sau:

NODE      EXPLANATION 
-------------------------------------------------------------------------------- 
    \n      '\n' (newline) 
-------------------------------------------------------------------------------- 
    --      '-- ' 
-------------------------------------------------------------------------------- 
    \n      '\n' (newline) 
-------------------------------------------------------------------------------- 
    .*?      any character except \n (0 or more times 
          (matching the least amount possible)) 
-------------------------------------------------------------------------------- 
    $      before an optional \n, and the end of the 
          string 

Theo tài liệu, "Không có hỗ trợ cho cú pháp biểu thức chính quy được thêm sau Perl phiên bản 5.6, đặc biệt là bất kỳ đồng nào nstructs được thêm vào trong 5.10 ", nhưng trong thực tế bạn vẫn có thể sử dụng nó để giúp hiểu hầu hết các regex bạn gặp phải.

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