Normal bir ifadede “bu karakter sırasına kadar olan her şey” nasıl eşleştirilir?


514

Bu normal ifade atın: /^[^abc]/. Bu, bir dizgenin başındaki a, b veya c dışında herhangi bir karakterle eşleşir.

Sonrasına bir eklerseniz *- /^[^abc]*/- normal ifade, sonuca sonraki karakterleri an a, veya b , veya ile karşılaşana kadar eklemeye devam eder c.

Örneğin, kaynak dizgiyle "qwerty qwerty whatever abc hello"ifade en fazla eşleşir "qwerty qwerty wh".

Peki ya eşleşen dizenin "qwerty qwerty whatever "

Başka bir deyişle, kesin diziye kadar olan her şeyi nasıl eşleştirebilirim (ancak dahil değil) "abc"?


Ne demek istiyorsun match but not including?
Toto

5
Yani "qwerty qwerty whatever ""abc" de dahil olmak üzere eşleştirmek istiyorum . Diğer bir deyişle, ben yok sonuçlanan maç olmasını istiyorum "qwerty qwerty whatever abc".
callum

2
Javascript sadece yapabilirsiniz do string.split('abc')[0]. Kesinlikle bu sorunun resmi bir cevabı değil, ama normal ifadeden daha basit buluyorum.
Wylliam Judd

Yanıtlar:


1020

Hangi regex lezzetini kullandığınızı belirtmediniz, ancak bu "tam" olarak kabul edilebilecek en popüler olanlardan herhangi birinde işe yarayacaktır.

/.+?(?=abc)/

Nasıl çalışır

.+? Bölüm un-açgözlü versiyonudur .+ (biri ya da bir şey daha fazla). Kullandığımızda .+, motor temel olarak her şeye uyacaktır. Daha sonra, normal ifadede başka bir şey varsa, aşağıdaki bölümle eşleşmeye çalışan adımlara geri dönecektir. Bu açgözlü davranış, tatmin etmek için mümkün olduğunca anlamlıdır .

Kullanırken .+?, hepsini bir kerede eşleştirmek ve diğer koşullara (varsa) geri dönmek yerine, normal ifadenin sonraki kısmı eşleşene kadar (eğer varsa) bir sonraki karakterleri adım adım eşleştirir. Bu açgözlü değil , yani tatmin etmek için mümkün olan en azıyla eşleşiyor .

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

Sahip olduğumuz ardından , bir sıfır genişlik iddiası , bir etrafına bakmak . Bu gruplandırılmış yapı içeriğiyle eşleşir, ancak eşleşen karakterler ( sıfır genişlik ) olarak sayılmaz . Yalnızca eşleşme olup olmadığı döndürülür ( onaylama ).(?={contents})

Böylece, diğer terimlerle, normal /.+?(?=abc)/ifade:

"Abc" bulunmadan "abc" bulunana kadar karakterleri mümkün olduğunca az eşleştirin.


12
Eğer yakalanmaları gerekiyorsa, bu muhtemelen satır sonlarıyla çalışmaz.
einord

3
Arasındaki fark nedir .+?ve .*?
robbie

4
@ robbie0630 +, 1 veya daha fazla *anlamına gelir ; burada 0 veya daha fazla anlamına gelir. İradenin dahil edilmesi / dışlanması ?onu açgözlü veya açgözlü yapmaz.
jinglesthula

2
@ testerjoe2 /.+?(?=abc|xyz)/
JohnWrensby

4
Aradığın desen yoksa, bunun hiçbir şey seçemediğini fark ettim, bunun yerine, kullanmazsan, istemediğin ^(?:(?!abc)(?!def).)*desenleri hariç tutmak için zincir oluşturabilirsin ve desen olmasa bile her şeyi gerektiği gibi yakalar
Karan Shishoo

122

"Abc" e kadar olan her şeyi yakalamak istiyorsanız:

/^(.*?)abc/

Açıklama:

( )kullanarak erişim için parantez içinde ifade yakalamak $1, $2vb

^ hattın başlangıç ​​maçı

.*?açgözlülükle bir şeyle eşleştir (gereken minimum karakter sayısını eşleştir) - [1]

[1] Bunun gerekli olmasının nedeni, aksi takdirde, aşağıdaki dizede olmasıdır:

whatever whatever something abc something abc

varsayılan olarak, normal ifadeler açgözlüdür , yani mümkün olduğu kadar eşleşir. Bu nedenle /^.*abc/"bir şey abc ne olursa olsun" ile eşleşir. Açgözlü olmayan niceleyiciyi eklemek ?normal ifadeyi yalnızca "her ne olursa olsun" ile eşleştirir.


4
Teşekkürler ama ne olursa yapar maçında abc sayılabilir. Başka bir deyişle, sonuçta elde edilen eşleşme "ne olursa olsun bir şey abc" dir.
callum

1
Sonunda ne yapmaya çalıştığınızı açıklayabilir misiniz? Senaryonuz: (A) Her şeyi "abc" ye götürmek istiyorsunuz - sadece yakalamak istediğiniz parantezleri kullanın. (B) Dizeyi "abc" ile eşleştirmek istiyorsunuz - yine de abc'yi kontrol etmeniz gerekiyor, bu yüzden ne olursa olsun normal ifadenin bir parçası olması gerekiyor. Orada olup olmadığını başka nasıl kontrol edebilirsiniz?
Jared Ng

sedaçgözlü olmayan eşleşmeyi desteklemiyor ve etrafa bakmayı da desteklemiyor ( (?=...)). Başka ne yapabilirim? Örnek komut: echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"döner two,three, FOUR FIVE, ancak two,three
beklerim

1
@CoDEmanX Muhtemelen bir yorumdan ziyade kendi ayrı sorunuz olarak yayınlamalısınız, özellikle de özellikle sed ile ilgili. Söylendiğine göre, sorunuzu ele almak için: bu sorunun cevaplarına bakmak isteyebilirsiniz . Ayrıca, örneğinizde, açgözlü olmayan bir tercümanın sadece geri dönmeyeceğini twounutmayın two,three.
Jared Ng

3
Bu nasıl her regexp'in cevabı gerektiğini bakmak - örnek ve tüm parçaların açıklaması ...
jave.web

54

@Jared Ng ve @Issun'un işaret ettiği gibi, bu tür RegEx'i "belirli bir kelimeye veya alt dizeye kadar her şeyi eşleştirmek" veya "belirli bir kelimeden veya alt dizeden sonra her şeyi eşleştirmek" gibi çözme anahtarına "lookaround" sıfır uzunluklu iddialar denir . Burada onlar hakkında daha fazla bilgi edinin.

Özel durumunuzda, ileriye dönük olumlu bir bakışla çözülebilir: .+?(?=abc)

Bir resim bin kelime değerinde bir olup. Ekran görüntüsünde ayrıntı açıklamasına bakın.

Regex101 Ekran Görüntüsü


23
.+?(?=abc)kopyalanabilen regex daha değerlidir.
Tom

Önde gelen alanları hariç tutmaya ne dersiniz?
Royi


7

Java regex için ve ben de çoğu regex motorları inanıyorum, eğer son kısmı dahil etmek istiyorsanız bu işe yarayacak:

.+?(abc)

Örneğin, bu satırda:

I have this very nice senabctence

"abc" ye kadar tüm karakterleri seçin ve abc'yi de ekleyin

normal ifademizi kullanarak, sonuç: I have this very nice senabc

Bunu test et: https://regex101.com/r/mX51ru/1


4

Sorunumu çözmek için yardım aradıktan sonra bu stackoverflow sorusunda sona erdim, ancak hiçbir çözüm bulamadım :(

Bu yüzden doğaçlama yapmak zorundaydım ... bir süre sonra ihtiyaç duyduğum düzenli ifadeye ulaşmayı başardım:

resim açıklamasını buraya girin

Gördüğünüz gibi, son satır eklemeden "grp-bps" klasöründen bir klasöre kadar ihtiyacım vardı. Ve "grp-bps" klasöründen sonra en az bir klasör olması gerekiyordu.

Düzenle

Kopyala yapıştır için metin sürümü (metniniz için 'grp-bps'yi değiştirin):

.*\/grp-bps\/[^\/]+

6
Metin sürümü yok mu? 🙄
kiradotee

2

Bu normal ifade hakkında anlamlı olacaktır.

  1. Tam kelime aşağıdaki regex komutundan alınabilir:

( "(. *?)") / G

Burada, çift tırnak içine alınmış olan kelimeyi global olarak elde edebiliriz. Örneğin, arama metnimiz

Bu "çift tırnaklı" kelimelere örnek

o zaman bu cümleden "çift tırnak" alınır.


StackOverflow'a hoş geldiniz ve yardım girişiminiz için teşekkürler. Ancak bunun soruda belirtilen hedefe nasıl yardımcı olduğunu görmekte zorlanıyorum. Detaylandırabilir misin? Verilen örneklere uygulayabilir misiniz? Bana odaklanılıyor gibi görünüyor ", ki bu bana soru ile ilgisiz geliyor.
Yunnosch

1
Merhaba, özel karakterler arasında kelimeyi veya cümleleri nasıl alacağımı açıkladım. Burada sorumuz "özel karakter dizisine kadar her şey" dir. Bu yüzden çift tırnak ile denedim ve burada açıkladı. Teşekkürler.
Ponmurugan Mohanraj

2

Python'da:

.+?(?=abc) tek satırlık durumda çalışır.

[^]+?(?=abc)çalışmaz, çünkü python [^] değerini geçerli normal ifade olarak tanımaz. Çok satırlı eşleşmeyi sağlamak için re.DOTALL seçeneğini kullanmanız gerekir, örneğin:

re.findall('.+?(?=abc)', data, re.DOTALL)

0

Alt ifadelere ihtiyacınız olduğuna inanıyorum. Doğru hatırlıyorsam (), alt ifadeler için normal parantezleri kullanabilirsiniz .

Bu bölüm grep kılavuzundan:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

^[^(abc)]Hile yapmak gibi bir şey yapın .


Üzgünüm, bu işe yaramıyor. Abc'yi parantez içine almak herhangi bir fark yaratmıyor gibi görünüyor. Hala "a OR b OR c" olarak muamele görürler.
callum

-1

$İşaretler bir dize sonu böyle bir şey çalışması gerekir böylece: [[^abc]*]$Eğer herhangi yineleme ile biten bir şey arıyorsanız burada abcama sonunda olması gerekir

Ayrıca regex (php veya js gibi) ile bir komut dosyası dili kullanıyorsanız, bir desenle ilk karşılaştığında duran bir arama işlevine sahiptirler (ve soldan başlamayı veya sağdan başlamayı veya php ile belirtebilirsiniz. dizeyi yansıtmak için bir implode yapabilirsiniz).


-6

bunu dene

.+?efg

Sorgu :

select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;

çıktı :

hijklmn
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.