2010-08-25 31 views
12

Làm thế nào để viết một regex phù hợp với một mẫu có thể chứa dấu ngoặc kép, nhưng nếu có, phải có dấu ngoặc kép phù hợp ở đầu và cuối?Làm cách nào để khớp một mẫu với dấu ngoặc kép xung quanh tùy chọn?

"?(pattern)"? 

Sẽ không hoạt động vì nó sẽ cho phép các mẫu bắt đầu bằng câu trích dẫn nhưng không kết thúc bằng một câu.

"(pattern)"|(pattern) 

Sẽ hoạt động, nhưng lặp lại. Có cách nào tốt hơn để làm điều đó mà không lặp lại mô hình?

+1

gì hương vị của regex bạn đang sử dụng? .Net cho phép loại "kết hợp ngoặc đơn" nhưng các hương vị khác thì không. – cristobalito

+0

Một khám phá có liên quan: http://stackoverflow.com/questions/3165755/capturing-thispartonly-and-thispartonly-with-the-same-group – polygenelubricants

Trả lời

17

Bạn có thể có được một giải pháp mà không lặp lại bằng cách sử dụng backreferencesconditionals:

/^(")?(pattern)(?(1)\1|)$/ 

Matches:

  • mẫu
  • "mẫu"

Liệu không khớp:

  • "mẫu
  • mẫu"

mô hình này là hơi phức tạp, tuy nhiên. Đầu tiên nó tìm kiếm một dấu ngoặc kép tùy chọn, và đặt nó vào backreference 1 nếu một được tìm thấy. Sau đó, nó tìm kiếm mẫu của bạn. Sau đó, nó sử dụng cú pháp có điều kiện để nói "nếu backreference 1 được tìm thấy một lần nữa, phù hợp với nó, nếu không phù hợp với không có gì". Toàn bộ mẫu là anchored (có nghĩa là nó cần tự xuất hiện trên một dòng) sao cho các dấu ngoặc kép không khớp sẽ không bị bắt (nếu không thì pattern trong pattern" sẽ khớp).

Lưu ý rằng hỗ trợ cho điều kiện thay đổi theo công cụ và biểu thức dài dòng hơn nhưng lặp đi lặp lại sẽ được hỗ trợ rộng rãi hơn (và dễ hiểu hơn).


Cập nhật: Một phiên bản đơn giản hơn nhiều của regex này sẽ /^(")?(pattern)\1$/, mà không cần một điều kiện. Khi tôi đã thử nghiệm này ban đầu, người thử nghiệm tôi đã sử dụng đã cho tôi một âm tính giả, dẫn tôi đến giảm giá nó (oops!).

Tôi sẽ để lại giải pháp với điều kiện cho hậu thế và sự quan tâm, nhưng đây là phiên bản đơn giản hơn có nhiều khả năng hoạt động trong nhiều loại động cơ hơn (backreferences là tính năng duy nhất được sử dụng tại đây có thể không được hỗ trợ).

+0

Aaarrg, tôi vừa bắt đầu tra cứu cú pháp điều kiện regex-if trong sách Friedel . Bạn đã nhanh hơn +1 (+1 tiếp theo là cho các mô hình đệ quy ;-) –

+0

@rubber Ngày xửa ngày xưa tôi biết làm thế nào để làm regex đệ quy nhưng tôi nghĩ rằng tôi quên vì lợi ích của nhân loại;) –

+0

@ Daniel: Nhân loại có lẽ sẽ không phiền nếu bạn quên cả điều kiện. '^ ("?) pattern \ 1 $ 'hoạt động tốt. (Câu trả lời đã xóa của wuputah không hoạt động vì nó không được neo. Và @Tim, các định lượng sở hữu/các nhóm nguyên tử không cần thiết.) –

0

Tùy thuộc vào ngôn ngữ bạn đang sử dụng, bạn sẽ có thể sử dụng tính năng trả lại. Một cái gì đó như thế này, nói:

(["'])(pattern)\1|^(pattern)$ 

Bằng cách đó, bạn đang yêu cầu không có dấu ngoặc kép hoặc báo giá CÙNG được sử dụng ở cả hai đầu.

0

Điều này sẽ hoạt động với regex đệ quy (cần lâu hơn để có quyền). Trong thời gian chờ đợi: trong Perl, bạn có thể tạo regex tự sửa đổi.Tôi sẽ để lại đó là một ví dụ học ;-)

my @stuff = ('"pattern"', 'pattern', 'pattern"', '"pattern' ); 

foreach (@stuff) { 
    print "$_ OK\n" if /^ 
         (")? 
         \w+ 
         (??{defined $1 ? '"' : ''}) 
         $ 
         /x 
} 

Kết quả:

"pattern" OK 
pattern OK 
Các vấn đề liên quan