Tôi có một ứng dụng mà người dùng có thể chỉ định cụm từ thông dụng ở một số địa điểm. Chúng được sử dụng khi chạy ứng dụng để kiểm tra xem văn bản (ví dụ: URL và HTML) có khớp với các regex hay không. Thường thì người dùng muốn có thể nói nơi văn bản khớp với ABC và không khớp với XYZ. Để làm cho nó dễ dàng cho họ để làm điều này tôi đang nghĩ đến việc mở rộng cú pháp biểu thức chính quy trong ứng dụng của tôi với một cách để nói 'và không chứa mẫu
Bạn không cần phải giới thiệu một biểu tượng mới. Đã có hỗ trợ cho những gì bạn cần trong hầu hết các động cơ regex. Nó chỉ là một vấn đề của việc học nó và áp dụng nó.
Bạn có lo ngại về hiệu suất, nhưng bạn đã thử nghiệm nó chưa? Bạn đã đo lường và chứng minh những vấn đề hiệu suất đó chưa? Nó có lẽ sẽ ổn thôi.
Regex làm việc cho nhiều người, trong nhiều tình huống khác nhau. Nó có thể phù hợp với yêu cầu của bạn, quá.
Ngoài ra, regex phức tạp mà bạn tìm thấy trên câu hỏi SO khác, có thể được đơn giản hóa. Có những biểu thức đơn giản cho những cái nhìn tiêu cực và tích cực và trông ngoài.
?!
?<!
?=
?<=
Vài ví dụ
Giả sử văn bản mẫu là <tr valign='top'><td>Albatross</td></tr>
Với các regex sau đây, đây là những kết quả bạn sẽ thấy:
tr
- - trận đấu
td
- - trận đấu
^td
- - không có trận đấu
^tr
- - không có trận đấu
^<tr
- - trận đấu
^<tr>.*</tr>
- - không có trận đấu
^<tr.*>.*</tr>
- - trận đấu
^<tr.*>.*</tr>(?<tr>)
- - trận đấu
^<tr.*>.*</tr>(?<!tr>)
- - không có trận đấu
^<tr.*>.*</tr>(?<!Albatross)
- - trận đấu
^<tr.*>.*</tr>(?<!.*Albatross.*)
- - không có trận đấu
^(?!.*Albatross.*)<tr.*>.*</tr>
- - không có trận đấu
Giải thích
Hai trận đấu đầu tiên vì regex có thể áp dụng ở bất kỳ đâu trong chuỗi mẫu (hoặc kiểm thử). Hai thứ hai không khớp, bởi vì ^ nói "bắt đầu từ đầu", và chuỗi thử nghiệm không bắt đầu bằng td hoặc tr - nó bắt đầu bằng một khung góc trái.
Ví dụ thứ năm phù hợp bởi vì chuỗi thử nghiệm bắt đầu bằng <tr
.
Thứ sáu không, bởi vì nó muốn chuỗi mẫu bắt đầu bằng <tr>
, với một khung góc đóng ngay sau tr
, nhưng trong chuỗi thử nghiệm thực tế, mở tr
bao gồm valign
thuộc tính, vì vậy những gì sau tr
là một không gian. Regex thứ 7 cho thấy cách cho phép không gian và thuộc tính với các ký tự đại diện.
Regex thứ 8 áp dụng xác nhận tích cực cho sự kết thúc của regex, sử dụng ?<
. Nó cho biết, chỉ khớp toàn bộ regex nếu những gì ngay trước con trỏ trong chuỗi thử nghiệm, khớp với những gì trong dấu ngoặc đơn, theo sau ?<
. Trong trường hợp này, những gì sau đó là tr>
. Sau khi đánh giá `` ^. *, the cursor in the test string is positioned at the end of the test string. Therefore, the
tr> `được so khớp với kết thúc của chuỗi kiểm tra, mà đánh giá là TRUE. Do đó, lookbehind tích cực được đánh giá là true, do đó regex tổng thể phù hợp.
Ví dụ thứ chín cho thấy cách chèn xác nhận lookbehind phủ định, sử dụng ?<!
. Về cơ bản nó nói "cho phép regex để phù hợp nếu những gì ngay phía sau con trỏ tại thời điểm này, không khớp với những gì sau ?<!
trong parens, trong trường hợp này là tr>
. Bit của regex trước khẳng định, ^<tr.*>.*</tr>
khớp với và bao gồm phần cuối của chuỗi. Bởi vì mô hình tr>
làm khớp với phần cuối của chuỗi. Nhưng đây là một khẳng định tiêu cực, do đó nó đánh giá thành FALSE, có nghĩa là ví dụ thứ 9 KHÔNG phải là một kết quả phù hợp.
Ví dụ thứ mười sử dụng một xác nhận lookbehind tiêu cực khác. Về cơ bản nó nói "cho phép regex để phù hợp nếu những gì ngay phía sau con trỏ tại thời điểm này, không khớp với những gì trong parens, trong trường hợp này Albatross
. Bit của regex trước khẳng định, ^<tr.*>.*</tr>
khớp với và bao gồm phần cuối của chuỗi. Kiểm tra "Albatross" so với kết thúc của chuỗi mang lại kết quả phủ định, bởi vì chuỗi kiểm tra kết thúc bằng </tr>
. Bởi vì các mẫu bên trong các parens của lookbehind tiêu cực không phù hợp, điều đó có nghĩa là lookbehind tiêu cực đánh giá để TRUE, có nghĩa là ví dụ thứ 10 là một trận đấu.
Ví dụ thứ 11 mở rộng giao diện tiêu cực để bao gồm các ký tự đại diện; trong tiếng Anh kết quả của lookbehind tiêu cực là "chỉ khớp nếu chuỗi trước không bao gồm từ AlbatrossTrong trường hợp này chuỗi kiểm tra DOES bao gồm từ, cái nhìn tiêu cực đánh giá là FALSE, và regex thứ 11 không khớp.
Ví dụ thứ 12 sử dụng xác nhận lookahead phủ định. Giống như lookbehinds, lookaheads là zero-width - chúng không di chuyển con trỏ trong chuỗi kiểm tra cho các mục đích của chuỗi phù hợp. Các lookahead trong trường hợp này, từ chối chuỗi ngay lập tức, bởi vì .*Albatross.*
kết quả phù hợp; bởi vì nó là một lookahead tiêu cực, nó đánh giá thành FALSE, có nghĩa là regex tổng thể không phù hợp, có nghĩa là đánh giá của regex đối với chuỗi kiểm tra dừng lại ở đó.
ví dụ 12 luôn luôn ước lượng giá trị boolean giống như ví dụ 11, nhưng nó hoạt động khác nhau trong thời gian chạy. Trong ví dụ 12, kiểm tra âm được thực hiện trước, tại các điểm dừng ngay lập tức. Trong ex 11, regex đầy đủ được áp dụng và đánh giá là TRUE, trước khi xác nhận lookbehind được chọn. Vì vậy, bạn có thể thấy rằng có thể có sự khác biệt về hiệu suất khi so sánh lookaheads và lookbehinds. Điều nào phù hợp với bạn tùy thuộc vào những gì bạn đang đối sánh và độ phức tạp tương đối của mẫu "đối sánh dương" và mẫu "đối sánh phủ định".
Để biết thêm về nội dung này, hãy đọc tại http://www.regular-expressions.info/
Hoặc có được một công cụ đánh giá regex và thử một số xét nghiệm.
như công cụ này:

nguồn và nhị phân
Bạn có thể dễ dàng hoàn thành mục tiêu của mình bằng cách sử dụng một regex đơn. Đây là một ví dụ minh họa một cách để làm điều đó. Regex này khớp với một chuỗi chứa "cat"
VÀ "lion"
VÀ "tiger"
, nhưng KHÔNG chứa "dog"
HOẶC LÀ "wolf"
HOẶC LÀ "hyena"
:
if (Regex.IsMatch(text, @"
# Match string containing all of one set of words but none of another.
^ # anchor to start of string.
# Positive look ahead assertions for required substrings.
(?=.*? cat ) # Assert string has: 'cat'.
(?=.*? lion ) # Assert string has: 'lion'.
(?=.*? tiger ) # Assert string has: 'tiger'.
# Negative look ahead assertions for not-allowed substrings.
(?!.*? dog ) # Assert string does not have: 'dog'.
(?!.*? wolf ) # Assert string does not have: 'wolf'.
(?!.*? hyena ) # Assert string does not have: 'hyena'.
",
RegexOptions.Singleline | RegexOptions.IgnoreCase |
RegexOptions.IgnorePatternWhitespace)) {
// Successful match
} else {
// Match attempt failed
}
Bạn có thể thấy mẫu cần thiết. Khi lắp ráp các regex, hãy chắc chắn để chạy mỗi người dùng cung cấp các chuỗi con thông qua Regex.escape () phương pháp để thoát khỏi bất kỳ metacharacters nó có thể chứa (tức là (
, )
, |
v.v.) Ngoài ra, regex ở trên được viết ở chế độ khoảng trống miễn phí để dễ đọc. Regex sản xuất của bạn nên KHÔNG PHẢI sử dụng chế độ này, nếu không khoảng trắng bên trong các dữ liệu người dùng sẽ bị bỏ qua.
Bạn có thể muốn thêm \b
từ ranh giới trước và sau mỗi "từ" trong mỗi khẳng định nếu các chất nền chỉ chứa các từ thực.
Cũng lưu ý rằng xác nhận tiêu cực có thể được thực hiện hiệu quả hơn một chút bằng cách sử dụng cú pháp thay thế sau đây:
(?!.*?(?:dog|wolf|hyena))