Làm thế nào để "đối sánh nghịch đảo" với regex?


112

Tôi đang sử dụng RegexBuddy nhưng tôi vẫn gặp rắc rối với điều này: \

Tôi đang xử lý từng dòng một tệp. Tôi đã xây dựng một "mô hình đường" để phù hợp với những gì tôi muốn.

Bây giờ tôi muốn thực hiện một phép so khớp nghịch đảo ... tức là tôi muốn so khớp các dòng trong đó có một chuỗi gồm 6 chữ cái, nhưng chỉ khi sáu chữ cái này không phảiAndrea , tôi nên làm như thế nào?


CHỈNH SỬA: Tôi sẽ viết chương trình sử dụng regex này, tôi chưa biết là trong python hay php, tôi đang làm điều này trước tiên để tìm hiểu một số regex :) Có nhiều loại dòng khác nhau , tôi muốn sử dụng regex để chọn loại mà tôi quan tâm. Khi tôi có những dòng này, tôi phải áp dụng một bộ lọc khác chỉ để không khớp với một giá trị đã biết, tôi cần tất cả những cái khác, không phải cái đó. (?! Not-want) đang hoạt động khá tốt, cảm ơn bạn. :-)

Tôi hy vọng điều này làm rõ câu hỏi :)


Thực ra có vẻ như bạn có thể làm tốt hơn khi cung cấp cho chúng tôi thêm một chút thông tin về những gì bạn đang làm và xem liệu ai đó có thể đưa ra giải pháp thay thế hay không. Thông thường, cố gắng phân tích cú pháp toàn bộ tệp bằng cách xây dựng một biểu thức chính quy khớp với mỗi dòng là một lộ trình khá phức tạp :)
Dan

Câu trả lời:


70
(?!Andrea).{6}

Giả sử công cụ regexp của bạn hỗ trợ những cái nhìn tiêu cực ..

Chỉnh sửa: .. hoặc có thể bạn muốn sử dụng [A-Za-z]{6}thay cho.{6}

Chỉnh sửa (một lần nữa): Lưu ý rằng nhìn chung và giao diện nhìn chung không phải là cách phù hợp để "nghịch đảo" đối sánh biểu thức chính quy. Regexps không thực sự được thiết lập để thực hiện đối sánh phủ định, chúng để lại điều đó cho bất kỳ ngôn ngữ nào bạn đang sử dụng chúng.


Bạn cần phải thêm ^ rằng @ Vinko Vrsalovic sử dụng để nó sẽ không phù hợp trên "ndrea \ n"
bdukes

2
. không khớp với \ n theo mặc định (một số ngôn ngữ [ví dụ: Perl] cho phép bạn bật hành vi đó, nhưng theo mặc định. khớp với mọi thứ NHƯNG \ n).
Dan

1
(thêm vào đó, OP không bao giờ đề cập đến chuỗi phải xảy ra ở đầu dòng)
Dan

1
ý bạn là gì đối với OP?
Andrea Ambu

1
Andrea: OP có nghĩa là "áp phích gốc", vì vậy, tôi đang đề cập đến bạn :)
Dan

47

Đối với Python / Java,

^(.(?!(some text)))*$

http://www.lisnichenko.com/articles/javapython-inverse-regex.html


4
Điều này không hiệu quả. Bạn đang nghĩ đến thành ngữ Mã thông báo tham lam. nhưng dấu chấm phải đi sau đầu nhìn, không phải trước. Xem câu hỏi này . Nhưng cách tiếp cận đó dù sao cũng là quá mức cần thiết cho nhiệm vụ này.
Alan Moore

Không biết nó được viết bằng ngôn ngữ nào, nhưng nó đã hoạt động như một sự quyến rũ trong văn bản Sublime để làm sạch dữ liệu thử nghiệm của tôi. Cảm ơn!
Matthias dirickx

1
@AlanMoore Trên thực tế, nó gần như sẽ hoạt động cho trường hợp sử dụng này. Tuy nhiên, nếu some textbắt đầu dòng, nó sẽ trả về kết quả sai.
Zenexer

2
@Zenexer, ý tôi là vậy. Nếu dấu chấm ở sau đầu nhìn thay vì trước đó, nó hoạt động hoàn hảo.
Alan Moore

Đây là một liên kết giải thích thêm. Tôi không hiểu tại sao ?!và không chỉ !.
Timo

21

Cập nhật với phản hồi từ Alan Moore

Trong PCRE và các biến thể tương tự, bạn thực sự có thể tạo regex khớp với bất kỳ dòng nào không chứa giá trị:

^(?:(?!Andrea).)*$

Đây được gọi là mã thông báo tham lam nóng tính . Nhược điểm là nó không hoạt động tốt.


1
Đây là Mã thông báo Tham lam Nhiệt độ ở dạng dài. Chỉ cần đặt dấu chấm (hoặc [\s\S], đó là chỉ hữu ích trong JavaScript) sau khi lookahead thứ hai, và bạn không cần phải là người đầu tiên: ^(?:(?!Andrea).)*$.
Alan Moore

@AlanMoore Đẹp! Tôi không thể tìm thấy bất kỳ mẫu đã thiết lập nào hoạt động như vậy, vì vậy tôi đã nghĩ ra mẫu của riêng mình. Thay vì tôi lấy câu trả lời của bạn, bạn nên cung cấp câu trả lời của riêng bạn.
Zenexer

Không sao, đã có rất nhiều câu trả lời hay. Và bạn xứng đáng được ghi công vì đã phát minh ra thành ngữ của riêng bạn. Chúc mừng!
Alan Moore

Tại sao bạn đề nghị sử dụng [\S\s]? OP đang nói về các dòng đối sánh, không chứa từ "Andrea". Không phải về việc kiểm tra xem toàn bộ chuỗi có chứa từ này hay không. Tui bỏ lỡ điều gì vậy?
x-yuri,

@ x-yuri Tôi nghĩ bạn đúng. Tôi có thể đã trả lời câu hỏi của tôi là lần đầu tiên tôi truy cập trang này, bỏ qua sự khác biệt. Kết nối của tôi là không đủ để cập nhật các câu trả lời tốt ngay bây giờ, mặc dù (<10 kbps)
Zenexer

11

Ngôn ngữ của bạn đang sử dụng là gì? Các khả năng và cú pháp của việc triển khai regex quan trọng cho việc này.

Bạn có thể sử dụng cái nhìn về phía trước. Sử dụng python làm ví dụ

import re

not_andrea = re.compile('(?!Andrea)\w{6}', re.IGNORECASE)

Để phá vỡ điều đó:

(?! Andrea) có nghĩa là 'khớp nếu 6 ký tự tiếp theo không phải là "Andrea"'; nếu vậy thì

\ w có nghĩa là "ký tự từ" - ký tự chữ và số. Điều này tương đương với lớp [a-zA-Z0-9_]

\ w {6} có nghĩa là chính xác 6 ký tự từ.

re.IGNORECASE có nghĩa là bạn sẽ loại trừ "Andrea", "andrea", "ANDREA" ...

Một cách khác là sử dụng logic chương trình của bạn - sử dụng tất cả các dòng không khớp với Andrea và đưa chúng qua regex thứ hai để kiểm tra 6 ký tự. Hoặc trước tiên hãy kiểm tra ít nhất 6 ký tự từ, sau đó kiểm tra xem nó có khớp với Andrea không.


7

Khẳng định tiêu cực nhìn trước

(?!Andrea)

Đây không hẳn là một trận đấu ngược, nhưng đó là cách tốt nhất bạn có thể làm trực tiếp với regex. Không phải tất cả các nền tảng đều hỗ trợ chúng.


1
Cho đến khi người hỏi làm rõ, tôi không thấy rằng trận đấu phải bắt đầu từ đầu dây. Vậy tại sao dấu ^?
Hamish Downer

Bởi vì tôi hiểu ông muốn kiểm tra vào đầu dòng, thay đổi nội dung làm rõ được
Vinko Vrsalovic

5

Nếu bạn muốn thực hiện việc này trong RegexBuddy, có hai cách để lấy danh sách tất cả các dòng không khớp với regex.

Trên thanh công cụ trên bảng Kiểm tra, đặt phạm vi kiểm tra thành "Từng dòng một". Khi bạn làm điều đó, một mục Liệt kê Tất cả các Dòng không có Phù hợp sẽ xuất hiện dưới nút Danh sách Tất cả trên cùng một thanh công cụ. (Nếu bạn không thấy nút Liệt kê tất cả, hãy nhấp vào nút Khớp trong thanh công cụ chính.)

Trên bảng điều khiển GREP, bạn có thể bật hộp kiểm "dựa trên dòng" và "đảo ngược kết quả" để nhận danh sách các dòng không khớp trong các tệp bạn đang duyệt qua.


5

(?!rất hữu ích trong thực tế. Mặc dù nói đúng ra, nhìn về phía trước không phải là biểu thức chính quy như được định nghĩa về mặt toán học.

Bạn có thể viết một biểu thức chính quy đảo ngược theo cách thủ công.

Đây là một chương trình để tính toán kết quả tự động. Kết quả của nó là do máy tạo ra, thường phức tạp hơn nhiều so với viết tay. Nhưng kết quả hoạt động.


1

Tôi vừa nghĩ ra phương pháp này có thể chuyên sâu về phần cứng nhưng nó đang hoạt động:

Bạn có thể thay thế tất cả các ký tự khớp với regex bằng một chuỗi trống.

Đây là một tấm lót:

notMatched = re.sub(regex, "", string)

Tôi sử dụng cái này vì tôi buộc phải sử dụng một regex rất phức tạp và không thể tìm ra cách đảo ngược mọi phần của nó trong một khoảng thời gian hợp lý.

Điều này sẽ chỉ trả về cho bạn kết quả chuỗi, không phải bất kỳ đối tượng khớp nào!


-3

Trong perl bạn có thể làm

process ($ line) if ($ line = ~! / Andrea /);


4
Cú pháp đó là sai. Tôi nghĩ ý bạn là xử lý ($ line) nếu $ line! ~ / Andrea /
dland
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.