2012-05-02 27 views
8

Tôi đã đọc tất cả các bài viết có liên quan và cọ rửa internet nhưng điều này thực sự đánh tôi.Làm thế nào để làm cho vẻ ngoài tiêu cực của Python ít tham lam hơn?

Tôi có một số văn bản chứa ngày.
Tôi muốn ghi lại ngày tháng, nhưng không phải là ngày bắt đầu bằng một cụm từ nhất định.

Một giải pháp đơn giản là thêm một giao diện tiêu cực vào RegEx của tôi.

Dưới đây là một số ví dụ (sử dụng findall).
Tôi chỉ muốn chụp ngày nếu nó không đứng trước cụm từ "tính đến".

19-2-11
một cái gì đó một cái gì đó 15-4-11
như vậy và như của 29-5-11

Đây là biểu hiện thường xuyên của tôi:

(?<!as of)(\d{1,2}-\d{1,2}-\d{2}) 

Kết quả mong đợi:

['19 -2-11 ']
['15 -4-11']
[]

Kết quả thực tế:

['19 -2-11' ]
['15 -4-11 ']
[' 9-5-11' ]

Thông báo đó là 9 không 29. Nếu tôi thay đổi \d{1,2} một cái gì đó vững chắc như \d{2} trên mô hình đầu tiên :

bad regex for testing: (?<!as of)(\d{2}-\d{1,2}-\d{2}) 

Sau đó tôi nhận được kết quả mong đợi. Tất nhiên điều này là không tốt bởi vì tôi muốn phù hợp với 2 chữ số ngày cũng như ngày một chữ số.

Dường như ngoại hình tiêu cực của tôi là tham lam quity - moreso hơn chụp ngày của tôi, vì vậy nó ăn cắp một chữ số từ nó và thất bại. Tôi đã thử mọi cách điều chỉnh tham lam mà tôi có thể nghĩ đến, nhưng tôi không biết sửa lỗi này.

Tôi muốn chụp ngày tháng của mình để phù hợp với tham lam tối đa, và sau đó giao diện tiêu cực của tôi được áp dụng. Điều này có thể không? Vấn đề của tôi có vẻ giống như một cách sử dụng tốt các ngoại hình tiêu cực và không quá phức tạp. Tôi chắc rằng tôi có thể thực hiện nó theo một cách khác nếu tôi phải nhưng tôi muốn học cách làm điều này.

Làm cách nào để làm cho giao diện phủ định của Python ít tham lam hơn?

Trả lời

1

Lý do không phải vì lookbehind là tham lam. Điều này xảy ra vì động cơ regex cố gắng khớp mẫu ở mọi vị trí có thể.

Tiến trình thông qua cụm từ such and such as of 29-5-11 khớp thành công (?<!as of) lúc đầu, nhưng không khớp với \d{1,2}.

Nhưng sau đó động cơ tìm thấy chính nó ở vị trí such and such as of !29-5-11 (được đánh dấu bằng !). Nhưng ở đây nó không phù hợp với (?<!as of).

Và nó tiến tới vị trí tiếp theo: such and such as of 2!9-5-11. Vị trí phù hợp thành công với (?<!as of) và sau đó là \d{1,2}.

Làm cách nào để tránh?

Giải pháp chung là xây dựng mẫu càng rõ ràng càng tốt.

Trong trường hợp này, tôi sẽ thêm chữ số vào trước với khoảng trắng cần thiết hoặc đầu chuỗi.

(?<!as of)(?:^|\s+)(\d{1,2}-\d{1,2}-\d{2}) 

Giải pháp của Mark Byers cũng rất tốt.

Tôi nghĩ rằng điều quan trọng là phải hiểu lý do tại sao động cơ regex hoạt động theo cách này và cho kết quả không mong muốn.

Bằng cách giải pháp tôi đưa ra ở trên không hoạt động nếu có từ 2 không gian trở lên. Nó không hoạt động vì vị trí nắm tay phù hợp ở đây such and such as of ! 29-5-11 với mẫu nêu trên.

Có thể làm gì để tránh điều này?

Thật không may trông giống như trong công cụ regex Python không hỗ trợ định lượng + hoặc *.

Tôi nghĩ rằng giải pháp đơn giản nhất sẽ là để đảm bảo không có khoảng trống trước (?:^|\s+) (meaing rằng tất cả các không gian được tiêu thụ bởi (?:^|\s+) thẳng sau khi bất kỳ văn bản nonspace (và trong trường hợp các văn bản là as of, chấm dứt việc thúc đẩy và quay lại với vị trí bắt đầu tiếp theo bắt đầu tìm kiếm khắp nơi một lần nữa tại các vị trí tiếp theo của văn bản đã tìm kiếm).

re.search(r'(?<!as of)(?<!\s)(?:^|\s+)(\d{1,2}-\d{1,2}-\d{2})','such and such as of 29-5-11').group(1) 
+0

Điều này thật tuyệt vời, tôi tìm thấy '(?:^| \ S +)' và lời giải thích của bạn rất rõ ràng. Tôi cảm thấy câu hỏi của tôi được trả lời.:) Hoàn toàn vì lợi ích của kiến ​​thức và không cần thiết tôi muốn tìm hiểu làm thế nào để sửa đổi này để '\ s' là tùy chọn, chẳng hạn như' something something15-4-11' sẽ phù hợp, nhưng tôi có thể nó ra bản thân mình. Cảm ơn bạn! –

+0

@ChristopherGalpin Tôi nghĩ rằng nó có thể đạt được rất dễ dàng bằng cách sử dụng '*' (từ 0 đến vô cùng xuất hiện) thay vì '+' (từ 1 đến vô cực) trong phần này của mẫu: '(?:^| \ S +) ' – ovgolovin

+0

Tôi đã hy vọng nó rất dễ dàng nhưng rõ ràng là không, phá vỡ' như của 'trận đấu trong cùng một cách như câu hỏi ban đầu. –

7

Điều này không liên quan gì đến tham lam. Sự bướng bỉnh không thay đổi cho dù một biểu thức chính quy có phù hợp hay không - nó chỉ thay đổi thứ tự mà tìm kiếm được thực hiện. Vấn đề ở đây là biểu thức chính quy của bạn cần phải cụ thể hơn để tránh các kết quả trùng khớp không mong muốn.

Để khắc phục nó, bạn có thể yêu cầu một ranh giới từ ngay trước khi trận đấu của bạn:

(?<!as of)\b(\d{1,2}-\d{1,2}-\d{2}) 
#   ^^ add this 
+0

Vâng, điều đó đã hiệu quả và bây giờ tôi cảm thấy câm. :) Cảm ơn yo u! Tôi biết điều này mở rộng câu hỏi ban đầu nhưng có một cách đơn giản tôi có thể gobble lên khoảng trắng giữa các cụm từ và ngày? Lookbehind phải có chiều rộng cố định để nó không thể đi vào đó, nhưng việc thêm \ s * gần ngày dường như hồi sinh lại vấn đề. –

+2

Làm thế nào về điều này: '(?

+0

Cảm ơn, tôi thấy điều này rất mang tính giáo dục. –

-1

Một giải pháp đơn giản có thể vứt bỏ tất cả các dòng phù hợp 'như của' trước khi sử dụng regex để cô lập các ngày

+2

"Fred là ông chủ của ngày hôm qua. Trong quyền lực kể từ ngày 31-12-11, ..." => FAIL –

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