Belirli bir alt dizenin ardından gelmeyen bir alt dizeyle eşleşen bir normal ifade


116

Eşleşecek blahfooblahancak eşleşmeyen bir normal ifadeye ihtiyacım varblahfoobarblah

Ardından bar gelmediği sürece sadece foo ve foo çevresindeki her şeyle eşleşmesini istiyorum.

Bunu kullanmayı denedim: foo.*(?<!bar)oldukça yakın ama uyuyor blahfoobarblah. Arkadaki olumsuz bakış, sadece çıtaya değil, her şeye uymalıdır.

Kullandığım özel dil, başlık altında Java regex'leri kullanan Clojure.

DÜZENLEME: Daha spesifik olarak, geçmesine de ihtiyacım var blahfooblahfoobarblahama değil blahfoobarblahblah.


1
Foo. * (? <! Bar. *) Kullanmayı denediniz mi?
Thibault Falise

Yanıtlar:


158

Deneyin:

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

Testler:

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

Normal ifade açıklaması

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

Diğer normal ifade

Yalnızca barhemen sonra olduğunda hariç tutmak fooistiyorsanız, kullanabilirsiniz

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

Düzenle

Sorunuzu spesifik hale getirmek için sorunuza güncelleme yaptınız.

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

Yeni testler

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

Yeni açıklama

(?=.*foo(?!bar))a'nın foobulunmasını sağlar , ancak doğrudan izlenmezbar


Bu çok yakın ve çok güzel bir cevap. Yeterince kesin olamayacağımı biliyordum. :( Buna ihtiyacım var: "blahfoomeowwoof / foobar /" yalnız "foo" yüzünden geçmek için, ancak bu blahfoobarmeowwoof değil. Bu mümkünse.
Rayne

Bir yan soru olarak, "bot" gibi bir şeyi eşleştirip "botter" eşleştirmeye nasıl gidilebilir?
Rayne

Evet. Şimdi sahip olduğum şeyi kullanabilirim, ancak botları eşleştirip botlarla eşleşmeseydim daha kolay olurdu. Çok üzgünüm. Normal ifadeler konusunda deneyimsizim ve korkarım ne istediğimi yavaş yavaş kendim çözüyorum. : p
Rayne

1
@Rayne, bu aynı soru. Yukarıdaki örneğinizde, eşleşmek istediniz fooama istemediniz foobar. Eşleştirmek için botama değil botters, kullanırsınız /(?=.*bot(?!ters))^(\w+)$/.
maček

Genelde bütün kelimeleri hedefliyordum. Dediğim gibi, gerçekten ne istediğim ve gerçekten neyin mümkün olduğu konusunda kafam karıştı. Böyle yapmak işe yarayacak. Zaman ayırdığınız için teşekkür ederim. :)
Rayne

55

fooAşağıdakileri ile başlamayan bir şeyle eşleştirmek için bardeneyin

foo(?!bar)

Negatif bakımlı sürümünüz etkili bir şekilde "a ile foobitmeyen bir şeyle eşleşir bar". Tümüyle .*eşleşir barblahve tekrar (?<!bar)bakar lahve eşleşmediğini kontrol eder bar, ki eşleşmez , yani tüm model eşleşir.


Bunu, "say" dizesi gelmediği sürece "yaptın mı" dizesiyle eşleşecek şekilde tasarlanmış bir normal ifade için denedim. Örneğin, "söyledin mi" ve "düşündün mü" arasında ayrım yaparken işe yarar, ancak sadece "yaptın mı" tek başına yakalanmaz ve olmalı. Baska öneri?
soosus

2

Bunun yerine olumsuz bir bakış kullanın:

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

Bu benim için çalıştı, umarım yardımcı olur. İyi şanslar!


Yinelenen dizeleri ("foofoo") hariç tutmak için de çalışan basit ama etkili normal ifade. Mükemmel!
Jonas Byström

1

Tüm dizenin kendisi yerine bir dizedeki tüm sözcüklerle eşleşmesini istediğinizi öneren bir yorum yazdınız.

Tüm bunları bir yorumda karıştırmak yerine, yeni bir cevap olarak gönderiyorum.

Yeni Normal İfade

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

Örnek yazı

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere venofuu ihtiyaçlarfoo

Maçlar

foowithbar fooevenwithfoobar foohere butfooisokherebar ihtiyaçlarfoo


0

Spesifik eşleşme isteğiniz şu şekilde eşleştirilebilir:

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

Bu eşleşecek blahfooblahfoobarblahama eşleşmeyecek blahfoobarblahblah.

Senin regex ile sorun foo.*(?<!bar)olduğunu .*sonra foo. Sonrasındaki karakterler dahil herhangi bir karakterle eşleşir bar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.