2010-10-13 25 views
107

Tôi có một danh sách các chuỗi. Một số trong số đó có dạng 123-...456. Phần biến "..." có thể là:Cách khớp, nhưng không chụp, một phần của một regex?

  • chuỗi "apple" sau dấu gạch ngang, ví dụ: 123-apple-456
  • chuỗi "chuối", theo sau là dấu nối, ví dụ: 123-banana-456
  • một chuỗi trống, ví dụ: 123-456 (lưu ý chỉ có một dấu nối)

Bất kỳ từ nào khác ngoài "táo" hoặc "chuối" đều không hợp lệ.

Đối với ba trường hợp này, tôi muốn đối sánh "quả táo", "chuối" và "" tương ứng. Lưu ý rằng tôi không bao giờ muốn chụp dấu gạch nối, nhưng tôi luôn muốn khớp với. Nếu chuỗi không thuộc dạng 123-...456 như được mô tả ở trên, thì không có kết quả nào cả.

Làm cách nào để viết biểu thức chính quy để thực hiện việc này? Giả sử tôi có một hương vị cho phép các nhóm nhìn, nhìn, nhìn chung và không bắt giữ.


Các quan sát quan trọng ở đây là khi bạn có một trong hai "quả táo" hoặc "chuối", bạn cũng phải có dấu nối dấu, nhưng bạn không muốn để phù hợp với nó. Và khi bạn khớp với chuỗi trống, bạn không được có dấu gạch ngang. Một regex mà đóng gói khẳng định này sẽ là một trong những quyền, tôi nghĩ.

+0

Phụ thuộc vào hương vị regex. Bạn đang sử dụng ngôn ngữ lập trình và/hoặc hương vị regex nào? – BoltClock

+0

@BoltClock: Đã thêm một số làm rõ. Cảm ơn vì bạn đã phản hồi. –

+0

Bạn muốn kết hợp mọi thứ trừ dấu gạch ngang? – BrunoLM

Trả lời

1

Hãy thử điều này:

/\d{3}-(?:(apple|banana)-)?\d{3}/ 
+1

Điều này không chính xác vì nó khớp, ví dụ: "123-dừa-456". –

+0

@david: khác với ví dụ "chuối" của bạn như thế nào? – SilentGhost

+0

@SilentGhost: I * only * muốn chụp 'apple' hoặc' banana' hoặc "". Tất cả các giá trị khác không hợp lệ, như tôi đã nói. –

7

Hãy thử:

123-(?:(apple|banana|)-|)456 

Điều đó sẽ phù hợp với apple, banana, hoặc một chuỗi trống, và sau đó sẽ có một 0 hoặc 1 dấu gạch ngang. Tôi đã sai về việc không cần một nhóm chụp hình. Tôi ngớ ngẩn quá.

+0

Điều này không chính xác vì nó khớp với, ví dụ: "123-dừa-456". –

+0

Nghĩ rằng bạn muốn nó tổng quát hơn ... cố định. – Thomas

+1

điều này sẽ khớp với ''123--456'' – SilentGhost

105

Cách duy nhất không để nắm bắt một cái gì đó đang sử dụng look-around assertions:

(?<=123-)((apple|banana)(?=-456)|(?=456)) 

Bởi vì ngay cả với non-capturing groups (?:…) toàn bộ biểu thức chính quy chụp nội dung phù hợp với họ. Nhưng biểu thức chính quy này chỉ khớp với apple hoặc banana nếu nó đứng trước 123- và theo sau là -456 hoặc biểu thức khớp với chuỗi trống nếu nó đứng trước 123- và tiếp theo là 456.

+1

+1 - Trong trường hợp này, bạn có thể làm việc xung quanh bằng cách sử dụng nhóm 1 thay vì nhóm 0, nhưng đây là sự khác biệt tuyệt vời (và tinh tế!). –

+0

@Ben Blank: Nó chắc chắn phụ thuộc vào cách "khớp" và "chụp" được diễn giải. – Gumbo

+5

Không được hỗ trợ trong JavaScript, * yay *! sẽ là tốt đẹp để có một phương pháp JS thân thiện, nhưng không phải là xấu cả, +0.5 (làm tròn lên; D) – GiantCowFilms

9

Cập nhật: Cảm ơn Germán Rodríguez Herrera!

Trong thử javascript: /123-(apple(?=-)|banana(?=-)|(?!-))-?456/

Hãy nhớ rằng kết quả là ở nhóm 1

Regular expression visualization

Debuggex Demo

-2

Cho đến nay đơn giản (chỉ hoạt động cho python) là '123-(apple|banana)-?456'.

+0

Điều này sẽ khớp với '123-apple456' để nó không chính xác. – Loren

1

tôi đã sửa đổi một trong những câu trả lời (bởi @ op1ekun):

123-(apple(?=-)|banana(?=-)|(?!-))-?456 

Lý do là câu trả lời từ @ op1ekun cũng phù hợp với "123-apple456", mà không có gạch nối sau khi táo.

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