Một regex để khớp với một chuỗi con không được theo sau bởi một chuỗi con khác nhất định


115

Tôi cần một regex sẽ phù hợp blahfooblahnhưng khôngblahfoobarblah

Tôi muốn nó chỉ khớp với foo và mọi thứ xung quanh foo, miễn là nó không được theo sau bởi thanh.

Tôi đã thử sử dụng cái này: foo.*(?<!bar)cái này khá gần, nhưng nó khớp blahfoobarblah. Cái nhìn tiêu cực đằng sau cần phải phù hợp với bất cứ điều gì và không chỉ thanh.

Ngôn ngữ cụ thể mà tôi đang sử dụng là Clojure sử dụng Java regexes.

EDIT: Đặc biệt hơn, tôi cũng cần nó để vượt qua blahfooblahfoobarblahnhưng không blahfoobarblahblah.


1
Bạn đã thử sử dụng foo. * (? <! Bar. *) Chưa?
Thibault Falise

Câu trả lời:


158

Thử:

/(?!.*bar)(?=.*foo)^(\w+)$/

Kiểm tra:

blahfooblah            # pass
blahfooblahbarfail     # fail
somethingfoo           # pass
shouldbarfooshouldfail # fail
barfoofail             # fail

Giải thích cụm từ thông dụng

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    bar                      'bar'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    foo                      'foo'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Regex khác

Nếu bạn chỉ muốn loại trừ barkhi nó diễn ra ngay sau đó foo, bạn có thể sử dụng

/(?!.*foobar)(?=.*foo)^(\w+)$/

Biên tập

Bạn đã cập nhật câu hỏi của mình để làm cho nó cụ thể.

/(?=.*foo(?!bar))^(\w+)$/

Các bài kiểm tra mới

fooshouldbarpass               # pass
butnotfoobarfail               # fail
fooshouldpassevenwithfoobar    # pass
nofuuhere                      # fail

Giải thích mới

(?=.*foo(?!bar))đảm bảo rằng a foođược tìm thấy nhưng không được theo dõi trực tiếpbar


Điều này rất gần, và một câu trả lời rất tốt. Tôi biết tôi sẽ không đủ cụ thể. :( Tôi cần cái này: "blahfoomeowwoof / foobar /" để vượt qua vì "foo" cô đơn, nhưng không phải blahfoobarmeowwoof này Nếu điều này có thể.
Rayne

Như một câu hỏi phụ, làm thế nào để kết hợp một cái gì đó như "bot" nhưng không phải "đáy"?
Rayne

Đúng. Tôi có thể sử dụng những gì tôi có bây giờ, nhưng sẽ dễ dàng hơn nếu tôi có thể kết hợp với bot chứ không thể ghép với đáy. Tôi rất xin lỗi. Tôi thiếu kinh nghiệm với regexes, và tôi sợ rằng mình đang dần tìm ra những gì bản thân muốn. : p
Rayne

1
@Rayne, đây là câu hỏi tương tự. Trong ví dụ trên, bạn muốn đối sánh foonhưng không khớp foobar. Để phù hợp botnhưng không botters, bạn sẽ sử dụng /(?=.*bot(?!ters))^(\w+)$/.
maček

Chà, tôi thường hướng tới toàn bộ từ ngữ. Như tôi đã nói, tôi bối rối về những gì tôi thực sự muốn và những gì thực sự có thể. Làm như thế này sẽ hiệu quả. Cảm ơn bạn đã dành thời gian. :)
Rayne

55

Để so khớp phần foosau với một thứ không bắt đầu bar, hãy thử

foo(?!bar)

Phiên bản của bạn với giao diện tiêu cực có hiệu quả là "kết hợp với một foocái gì đó theo sau bởi một cái gì đó không kết thúc bằng bar". Các mẫu .*trùng khớp với tất cả barblah, và (?<!bar)xem xét lại lahvà kiểm tra xem nó không khớp bar, cái nào không khớp , vì vậy toàn bộ mẫu khớp với nhau.


Vì vậy, tôi đã thử điều này cho một regex được thiết kế để khớp với chuỗi "did you", miễn là nó không được theo sau bởi "say". Nó hoạt động khi phân biệt giữa "bạn đã nói" và "bạn có nghĩ không", nhưng chỉ riêng "bạn đã nói" thì không được nắm bắt, và nó nên làm. Bất kỳ đề xuất?
soosus

2

Thay vào đó, hãy sử dụng cái nhìn tiêu cực về phía trước:

\s*(?!\w*(bar)\w*)\w*(foo)\w*\s*

Điều này làm việc cho tôi, hy vọng nó sẽ giúp. Chúc may mắn!


Regex đơn giản nhưng hiệu quả, cũng hoạt động để loại trừ các chuỗi lặp lại ("foofoo"). Hoàn hảo!
Jonas Byström

1

Bạn đã viết một nhận xét gợi ý rằng bạn thích điều này để khớp tất cả các từ trong một chuỗi thay vì toàn bộ chuỗi.

Thay vì trộn tất cả những điều này trong một bình luận, tôi đăng nó như một câu trả lời mới.

Regex mới

/(?=\w*foo(?!bar))(\w+)/

Văn bản mẫu

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu needfoo

Diêm

foowithbar fooevenwithfoobar foohere butfooisokherebar needfoo


0

Yêu cầu đối sánh cụ thể của bạn có thể được đối sánh bằng:

\w+foo(?!bar)\w+

Điều này sẽ phù hợp blahfooblahfoobarblahnhưng không blahfoobarblahblah.

Vấn đề với regex của bạn foo.*(?<!bar).*sau foo. Nó khớp với nhiều ký tự bất kỳ bao gồm các ký tự sau bar.

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.