Pertanyaan Sebuah regex untuk mencocokkan substring yang tidak diikuti oleh substring lainnya


Saya membutuhkan regex yang akan cocok blahfooblah tapi tidak blahfoobarblah

Saya ingin hanya mencocokkan foo dan segala sesuatu di sekitar foo, asalkan tidak diikuti oleh bar.

Saya mencoba menggunakan ini: foo.*(?<!bar) yang cukup dekat, tetapi cocok blahfoobarblah. Tampilan negatif di belakang perlu mencocokkan apa saja dan bukan hanya bilah.

Bahasa khusus yang saya gunakan adalah Clojure yang menggunakan Java regexes di bawah kap mesin.

EDIT: Lebih khusus lagi, saya juga membutuhkannya untuk lulus blahfooblahfoobarblah tapi tidak blahfoobarblahblah.


75
2018-04-13 15:48


asal


Jawaban:


Mencoba:

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

Tes:

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

Penjelasan ekspresi reguler

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 lainnya

Jika Anda hanya ingin mengecualikan bar ketika langsung setelah foo, Kamu dapat memakai

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

Edit

Anda membuat pembaruan untuk pertanyaan Anda untuk membuatnya spesifik.

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

Tes baru

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

Penjelasan baru

(?=.*foo(?!bar)) memastikan a foo ditemukan tetapi tidak diikuti secara langsung bar


104
2018-04-13 15:51



Untuk mencocokkan foo diikuti oleh sesuatu yang tidak dimulai bar, coba

foo(?!bar)

Versi Anda dengan tampilan negatif secara efektif "cocok dengan foo diikuti oleh sesuatu yang tidak berakhir bar" .* cocok semua barblah, dan (?<!bar) melihat kembali lah dan periksa bahwa itu tidak cocok bar, yang tidak, sehingga seluruh pola cocok.


39
2018-04-13 16:00



Gunakan tampilan negatif di depan sebagai gantinya:

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

Ini berhasil bagi saya, semoga itu membantu. Semoga berhasil!


2
2018-04-13 15:59



Permintaan pertandingan spesifik Anda dapat dicocokkan dengan:

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

Ini akan cocok blahfooblahfoobarblah tapi tidak blahfoobarblahblah.

Masalah dengan regex Anda foo.*(?<!bar) adalah .* setelah foo. Ini cocok dengan banyak karakter termasuk karakter setelahnya bar.


1
2018-04-13 16:21



Anda menulis komentar yang menyarankan Anda seperti ini untuk bekerja mencocokkan semua kata dalam string daripada seluruh string itu sendiri.

Daripada menumbuk semua ini dalam komentar, saya mempostingnya sebagai jawaban baru.

Regex baru

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

Contoh teks

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu needsfoo

Cocok

foowithbar fooevenwithfoobar foohere butfooisokherebar needsfoo


1
2018-04-13 17:23