Khớp mọi thứ trừ các chuỗi được chỉ định


118

Tôi biết rằng regex sau đây sẽ khớp với "đỏ", "xanh" hoặc "xanh".

red|green|blue

Có cách nào đơn giản để làm cho nó khớp với mọi thứ trừ một số chuỗi được chỉ định không?


1
Không phải tất cả các hương vị của biểu thức thông thường có thể làm điều này. Bạn đang làm việc trong môi trường nào? Java? Perl? .MẠNG LƯỚI? Một số thư viện regex C / C ++? Một RDBMS?
Thất vọngWithFormsDesigner

8
Bạn không nói những gì bạn muốn, nhưng bạn có thể chỉ cần đảo ngược ý nghĩa của hoạt động "khớp". Điều này sẽ không giúp ích cho bạn nếu bạn đang cố gắng trích xuất trên các phần không khớp, nhưng để kiểm tra xem một chuỗi loại trừ không có mặt hay không, nó sẽ hoạt động: if (!s.match(/red|green|blue/)) ... Lưu ý: Tôi biết rằng OP không chỉ định ngôn ngữ / khung nào, vì vậy trước đó nên được coi là một ví dụ chung chung, không phải là một ví dụ quy định.
tvanfosson

Câu trả lời:


152

Nếu bạn muốn chắc chắn rằng chuỗi không có màu đỏ, xanh lá cây hay xanh lam, câu trả lời của caskey là nó. Tuy nhiên, điều thường muốn là đảm bảo rằng dòng không chứa màu đỏ, xanh lá cây hoặc xanh dương ở bất cứ đâu trong đó. Vì thế, hãy neo biểu thức chính quy với ^và bao gồm .*trong giao diện phủ định:

^(?!.*(red|green|blue))

Ngoài ra, giả sử rằng bạn muốn các dòng có chứa từ "engine" nhưng không có bất kỳ màu nào trong số đó:

^(?!.*(red|green|blue)).*engine

Bạn có thể nghĩ rằng bạn có thể tính .*đến phần đầu của biểu thức chính quy:

^.*(?!red|green|blue)engine     # Does not work

nhưng bạn không thể. Bạn phải có cả hai trường hợp .*để nó hoạt động.


48

Phụ thuộc vào ngôn ngữ, nhưng nhìn chung có những khẳng định tiêu cực mà bạn có thể đưa vào như vậy:

(?!red|green|blue)

(Cảm ơn đã sửa lỗi cú pháp, ở trên là hợp lệ Java và Perl, YMMV)


2
@caskey, Câu trả lời đầy đủ là sự kết hợp giữa tôi và bạn. Nếu bạn muốn hợp nhất chúng lại với nhau, tôi sẽ xóa của tôi.
Wayne Conrad

13
Câu trả lời này sẽ hữu ích hơn rất nhiều là bạn giải thích nó một chút. Ví dụ: Làm gì "?" và "!" nghĩa là? Tại sao bạn cần chụp nhóm?
Lii

Đó cũng là Python hợp lệ.
Joe Mornin 17/03/2015

chỉ sử dụng cái này với thư viện regEx Delphi và nó chỉ hoạt động như thế này: ^ (?! đỏ | xanh | xanh). Cũng đúng khi thử nghiệm nó trên regex101.com . Vì vậy, một lỗi đánh máy ở trên thiếu một ^ hoặc nó thực sự hoạt động như thế trong Java / Perl / Python ..?
Peter

31

Phù hợp với bất cứ điều gì nhưng cho chuỗi

Nếu bạn muốn khớp toàn bộ chuỗi nơi bạn muốn khớp mọi thứ nhưng một số chuỗi nhất định bạn có thể làm như thế này:

^(?!(red|green|blue)$).*$

Điều này nói rằng, bắt đầu trận đấu từ đầu chuỗi, nơi nó không thể bắt đầu và kết thúc bằng màu đỏ, xanh lá cây hoặc xanh lam và khớp bất cứ thứ gì khác với cuối chuỗi.

Bạn có thể dùng thử tại đây: https://regex101.com/r/rMbYHz/2

Lưu ý rằng điều này chỉ hoạt động với các công cụ regex hỗ trợ giao diện tiêu cực .


23

Bạn không cần cái nhìn tiêu cực. Có ví dụ làm việc:

/([\s\S]*?)(red|green|blue|)/g

Sự miêu tả:

  • [\s\S] - phù hợp với bất kỳ nhân vật
  • * - khớp từ 0 đến không giới hạn từ nhóm trước
  • ? - khớp càng ít càng tốt
  • (red|green|blue|) - khớp một trong những từ này hoặc không có gì
  • g - lặp lại mô hình

Thí dụ:

whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

Sẽ là:

whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

Kiểm tra nó: regex101.com


4
Bạn có thể giảm đáng kể số bước bằng cách hoán đổi [\ s \ S] cho một dấu chấm. Tôi đã rất bối rối tại sao dường như mọi ví dụ khác đều nắm bắt từng từ riêng lẻ. Cách này là các bước regex nhiều hơn một chút nhưng yêu cầu xử lý hậu kỳ ít hơn nhiều.
Zatronium

3
nhưng điều này không phù hợp (xác thực văn bản), nó chỉ xóa văn bản được chỉ định trong khi thay thế.
Marek R

Giải pháp này sẽ không xuất ra đoạn văn bản cuối cùng sau những từ đã biết. Vì vậy, không cần so sánh tốc độ, nó chỉ là sai.
Wiktor Stribiżew

@ WiktorStribiżew đã sửa.
hlcs

10

Tôi có cùng một câu hỏi, các giải pháp được đề xuất gần như đã hoạt động nhưng chúng có một số vấn đề. Cuối cùng, regex tôi sử dụng là:

^(?!red|green|blue).*

Tôi đã thử nó trong Javascript và .NET.

. * không nên được đặt bên trong giao diện tiêu cực như thế này: ^ (?!. * đỏ | xanh | xanh) hoặc nó sẽ làm cho phần tử đầu tiên hoạt động khác với phần còn lại (nghĩa là "khác" sẽ không khớp khác xanh "sẽ)


3

Phù hợp với bất kỳ văn bản nào nhưng những văn bản phù hợp với một mẫu thường đạt được bằng cách tách chuỗi với mẫu regex .

Ví dụ :

  • - Regex.Split(text, @"red|green|blue")hoặc, để loại bỏ các giá trị trống, Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(xem bản demo )
  • - Regex.Split(text, "red|green|blue")hoặc, để xóa các mục trống, Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(xem bản demo hoặc bản demo này nơi LINQ được hỗ trợ)
  • - text.split(/red|green|blue/)(không cần sử dụng công cụ gsửa đổi ở đây!) (để loại bỏ các giá trị trống, sử dụng text.split(/red|green|blue/).filter(Boolean)), xem bản demo
  • - text.split("red|green|blue"), hoặc - để giữ tất cả các mục trống theo dõi - sử dụng text.split("red|green|blue", -1)hoặc để xóa tất cả các mục trống, hãy sử dụng thêm mã để xóa chúng (xem bản demo )
  • - Tương tự như Java, text.split(/red|green|blue/)để sử dụng tất cả các mục theo dõi text.split(/red|green|blue/, -1)và loại bỏ tất cả các mục trống sử dụng text.split(/red|green|blue/).findAll {it != ""})(xem bản demo )
  • - text.split(Regex("red|green|blue"))hoặc, để xóa các mục trống, sử dụng text.split(Regex("red|green|blue")).filter{ !it.isBlank() }, xem bản demo
  • - text.split("red|green|blue")hoặc để giữ tất cả các mục trống theo dõi, sử dụng text.split("red|green|blue", -1)và để xóa tất cả các mục trống, hãy sử dụng text.split("red|green|blue").filter(_.nonEmpty)(xem bản demo )
  • - text.split(/red|green|blue/), để loại bỏ các giá trị trống, hãy sử dụng .split(/red|green|blue/).reject(&:empty?)(và để có cả các mục trống dẫn đầu và theo dõi, sử dụng -1làm đối số thứ hai, .split(/red|green|blue/, -1)) (xem bản demo )
  • - my @result1 = split /red|green|blue/, $text;, hoặc với tất cả các mục trống theo dõi my @result2 = split /red|green|blue/, $text, -1;, hoặc không có bất kỳ mục trống nào, my @result3 = grep { /\S/ } split /red|green|blue/, $text;(xem bản demo )
  • - preg_split('~red|green|blue~', $text)hoặc preg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)để xuất không có mục trống (xem bản demo )
  • - re.split(r'red|green|blue', text)hoặc, để xóa các mục trống, list(filter(None, re.split(r'red|green|blue', text)))(xem bản demo )
  • - Sử dụng regexp.MustCompile("red|green|blue").Split(text, -1)và nếu bạn cần xóa các mục trống, hãy sử dụng mã này . Xem bản demo đi .

LƯU Ý : Nếu các mẫu của bạn chứa các nhóm bắt giữ , các hàm / phương thức phân chia regex có thể hoạt động khác nhau, cũng tùy thuộc vào các tùy chọn bổ sung. Vui lòng tham khảo các tài liệu phương pháp phân chia thích hợp sau đó.


0

Tất cả ngoại trừ từ "đỏ"

var href = '(text-1) (red) (text-3) (text-4) (text-5)';

var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Tất cả ngoại trừ từ "đỏ"

var href = '(text-1) (frede) (text-3) (text-4) (text-5)';

var test = href.replace(/\(([\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = p1.replace(/red/g, '');
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.