Normal İfadeler: VE işleci var mı?


708

Açıkçası, |temsil etmek için (boru?) Kullanabilirsiniz OR, ancak temsil etmenin bir yolu var ANDmı?

Özellikle, belirli bir ifadenin TÜMÜ'nü içeren, ancak belirli bir sırada olmayan metin paragraflarını eşleştirmek istiyorum.


1
Yani, her bir ifadenin belirli bir ifadedeki kelimelerin geçerli bir permütasyonu olduğu bir metinde ifadeler bulmak istediğiniz anlamına mı geliyorsunuz?
Nietzche-jou

2
Bunu buraya koyuyorum çünkü üç ya da dört cevap onu görmezden geliyor. Lookahead, $ ile bitmedikleri sürece her bir madde için aynı uzunlukla eşleşmez. Bir göz dört karakter ve diğer 6 karakterle eşleşebilir. Örneğin, (? = A *) (? = Aab) aabaaaaba
Zachary Vance

2
"AND" operatörü için yalnızca "boşluk" karakterini kullanmayı deneyin.

1. I'd like to match paragraphs of text. 2. Sıra dışı metin içeren . 1 numara yoruma açıktır. 2 numara birkaç yolla yapılabilir. Yol 1:, (?:(?:(?(1)(?!))\b(phrase1)\b.*?|(?(2)(?!))\b(phrase2)\b.*?)){2}Yol 2: (?=.*\bphrase1\b)(?=.*\bphrase2\b)burada, bu durumda paragrafın eşleştirilmesi paragraf tanımı resmileştirilinceye kadar tanımsızdır.

Yanıtlar:


386

Tükenmeyen düzenli bir ifade kullanın.

Tipik (yani Perl / Java) gösterimi:

(?=İfade)

Bu araçlar "maç İfade ama bundan sonra orijinal maç noktasında eşleşen devam eder."

Bunlardan istediğiniz kadarını yapabilirsiniz ve bu bir "ve" olacaktır. Misal:

(?=match this expression)(?=match this too)(?=oh, and this)

İçindeki bazı verileri kaydetmeniz gerekiyorsa, tüketmeyen ifadelerin içine yakalama grupları bile ekleyebilirsiniz.


3
perl -e "q {bazı şeyler ve şeyler} = ~ / (? = bazı) (? = şeyler) (? = şeyler) /? yazdır" evet ":" hayır "yazdır" hayır "yazdırır.
Robert P

27
Bu özel örneğin olumlu bir ileriye dönük iddiası olarak adlandırıldığı belirtilmelidir. "Ve" dışında başka kullanımları vardır. Metnin tüketilmediğini unutmayın.
09:11

7
Bunun gibi (? =) Kullanılması, asla başarılı olamayacak bir normal ifade ile sonuçlanır. Ama olduğu | için birlikte analog. OP sorununu çözeceğini düşündüğü şeyde yanlıştır.
Nietzche-jou

10
perl -e "q {bazı şeyler ve şeyler} = ~ /(?=.*some)(?=.*stuff)(?=.*things)/? yazdır" evet ":" hayır "yazdır
kriss

3
Cevabınızdaki perl koduna kolay bir örnek ekleyebilir misiniz?
Pithikos

344

Diğer yanıtlayıcıların bazılarının söylediği gibi lookahead'i kullanmanız gerekir, ancak lookahead'in hedef sözcüğü ile geçerli eşleşme konumu arasındaki diğer karakterleri hesaba katması gerekir. Örneğin:

(?=.*word1)(?=.*word2)(?=.*word3)

.*İlk lookahead o buna "word1" bulmadan gerekiyor ancak birçok karakterlerle eşleşen sağlar. Sonra eşleşme konumu sıfırlanır ve ikinci ileriye doğru "word2" arar. Yeniden sıfırlayın ve son bölüm "word3" ile eşleşir; kontrol ettiğiniz son kelime olduğu için, bunun bir göz önünde olması gerekli değildir, ancak zarar vermez.

Bir paragrafın tamamını eşleştirmek için, normal ifadeyi her iki uçta tutturmanız .*ve kalan karakterleri tüketmek için bir final eklemeniz gerekir. Perl tarzı gösterimi kullanmak, şöyle olur:

/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m

'M' değiştirici çok satırlı mod içindir; paragraf sınırlarında ^ve $eşleşmesine izin verir (normal ifadede "satır sınırları"). Size bu durumda önemlidir değil kullanmak 's' değiştirici, nokta işleci maç yeni satır yanı sıra tüm diğer karakterler sağlayan bir özelliktir.

Son olarak, sadece daha uzun kelimelerin parçalarını değil, tüm kelimeleri eşleştirdiğinizden emin olmak istersiniz, bu nedenle kelime sınırları eklemeniz gerekir:

/^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b).*$/m

8
Kesinlikle doğru - bu konuda da bir öğretici var! ocpsoft.org/tutorials/regular-expressions/and-in-regex
Lincoln

9
Çok teşekkürler. * Bu bir fark yaratıyor
Gennadiy Ryabkin

1
Tarama uçları için en iyi kullanımlardan birini gösteren net ve kısa yanıt için +1 (bir parolanın yüzde eşleşmesini saymak için kesmek gibi kullanımların aksine). :)
zx81

1
@Liam :. MySQL POSIX ERE lezzetini kullanır, bu yüzden hayır. Benim için makul görünen performans lehine özellikleri etkili bir şekilde feda eder. Burada daha fazla bilgi var .
Alan Moore

3
yerine .*ile [\s\S]*siz yeni çizgiler varsa javascript .yeni satırlar eşleşmiyor javascript en düzenli ifade motoru ve düzenleyiciler ile yapılan olamaz
Wesley Smith

41

Şu örneğe bakın:

2 regexps A ve B'ye sahibiz ve her ikisini de eşleştirmek istiyoruz, bu yüzden sözde kodda şöyle görünüyor:

pattern = "/A AND B/"

AND işlecini şu şekilde kullanmadan yazılabilir:

pattern = "/NOT (NOT A OR NOT B)/"

PCRE içinde:

"/(^(^A|^B))/"

regexp_match(pattern,data)

24
Biçimsel mantık açısından bu doğrudur, ancak burada kesinlikle yardım yoktur. Normal ifadelerde, ifade etmek VE'den daha zor olamaz.
Alan Moore

@marvin_dpr Diğer önerim (?=expr)olmasa da CMake'de benim için çalıştı . Uygulamaya bağlı gibi görünüyor.
Melebius

38
^Normal ifade sözdiziminde "dizenin başlangıcı" anlamına mı gelmez?
Lambda Fairy

3
Genel olarak normal ifade, ^sadece bir karakter sınıfının başlangıcında olumsuzluktur. CMake gerçekten korkak bir şey yapmadıkça (kendi desen eşleştirme dilini "regex" olarak adlandırmanın yanıltıcı veya yanlış olarak kabul edilebileceği noktaya kadar), sizin için çalıştığı gerçeğinin izole bir kaza olduğunu tahmin ediyorum.
tripleee

29

Bunu düzenli bir ifade ile yapabilirsiniz, ancak muhtemelen başka bir şey yapmak isteyeceksiniz. Örneğin birkaç regexp kullanın ve bunları bir if deyiminde birleştirin.

Tüm olası permütasyonları şu şekilde standart bir normal ifadeyle numaralandırabilirsiniz (herhangi bir sırayla a, b ve c ile eşleşir):

(abc)|(bca)|(acb)|(bac)|(cab)|(cba)

Ancak, çift terimden fazlasına sahipseniz, bu çok uzun ve muhtemelen verimsiz bir regexp yapar.

Perl veya Java gibi bazı genişletilmiş normal ifade sürümünü kullanıyorsanız, bunu yapmanın daha iyi yolları vardır. Diğer cevaplar olumlu ileriye dönük işlem kullanılmasını önerdi.


10
Yaklaşınızın geri tepme ile 3 ileri bakıştan daha verimsiz olduğunu düşünmüyorum. Yazmanın daha uzun olduğundan emin olun, ancak deseni otomatik olarak kolayca oluşturabileceğinizi unutmayın. Daha hızlı başarısız olacak şekilde geliştirebileceğinizi unutmayın a(bc|cb)|b(ac|ca)|c(ab|ba). Ve en önemlisi, tüm regex lezzeti ile kullanabilirsiniz.
Casimir et Hippolyte

27

AND operatörü olan örtülü RegExp sözdiziminde.
OR operatörü bunun yerine bir boru ile belirtilmelidir.
Aşağıdaki RegExp:

var re = /ab/;

harfi demektir a VE mektubu b.
Ayrıca gruplarla çalışır:

var re = /(co)(de)/;

o grubu anlamına gelmektedir co VE grubu de.
(Örtük) AND'in bir OR ile değiştirilmesi aşağıdaki satırları gerektirir:

var re = /a|b/;
var re = /(co)|(de)/;

29
Ne yazık ki, OP'nin istediği bu değil. Bu sırayla her şeyi bulur, oysa istedikleri sırayla isterler. Cevabı aşağıda doğru olan stackoverflow.com/users/20938/alan-moore ile kontrol edin .
JESii

1
@JESii Puanınız için teşekkürler, haklısınız ve Hugoware'den gelen soruyu yanlış anladım, özellikle ilk cümlesine odaklandım. AlanMoore'un yazdığı gibi, doğru cevap, ileriye doğru operatörün doğru kullanımıdır. Her neyse, birisinin açıklamamı zaten kaldırıldığı gibi yararlı bulabileceğini düşünüyorum, bu yüzden her şeyi atmam. Saygılarımızla.
Emanuele Del Grande

13

Sizin durumunuzda AND ile eşleşen birkaç sonuç yapmak mümkün değil mi? sözde kodda

regexp_match(pattern1, data) && regexp_match(pattern2, data) && ...

3
Kuralın geçerliliğini test etmek için tek bir regex desen eşleme dizesi ile kuralların bir veri tablosu olan bazı kod var bir durumda değilim. Birden fazla teste geçmek benim durumumda ve diğer insanların vakalarında da yapabileceğim bir şey değil!
Alan Wolfe

11

Neden awk kullanmıyorsunuz?
awk regex ile VEYA VEYA konularda çok basit

awk '/WORD1/ && /WORD2/ && /WORD3/' myfile

9

Perl normal ifadelerini kullanıyorsanız, olumlu ileriye bakabilirsiniz:

Örneğin

(?=[1-9][0-9]{2})[0-9]*[05]\b

100'den büyük sayılar ve 5'e bölünebilir


8

Çıktınızı başka bir normal ifadeye bağlayabilirsiniz. Grep kullanarak şunları yapabilirsiniz:

grep A | grep B


8

Kabul edilen cevaba ek olarak

Size bazılarınız için işleri daha net hale getirecek bazı pratik örnekler vereceğim. Örneğin, şu üç metin satırına sahip olduğumuzu varsayalım:

[12/Oct/2015:00:37:29 +0200] // only this + will get selected
[12/Oct/2015:00:37:x9 +0200]
[12/Oct/2015:00:37:29 +020x]

Demoyu buradan izleyin DEMO

Burada yapmak istediğimiz şey + işaretini seçmek, ancak sadece boşluklu iki sayıdan sonra ve dört sayıdan önce ise. Bunlar sadece kısıtlamalar. Bu düzenli ifadeyi elde etmek için kullanırız:

'~(?<=\d{2} )\+(?=\d{4})~g'

İfadeyi ayırırsanız bunun size farklı sonuçlar vereceğini unutmayın.

Ya da belki etiketler arasında bir metin seçmek istersiniz ... ama etiketler değil! Sonra kullanabilirsiniz:

'~(?<=<p>).*?(?=<\/p>)~g'

bu metin için:

<p>Hello !</p> <p>I wont select tags! Only text with in</p> 

Demoyu buradan izleyin DEMO


Kabul edilen cevap hangi cevaptı? Lütfen gelecekteki benim için bir bağlantı ekleyin.
James Brown

6

Düzen her zaman düzenli ifadenin yapısında ima edilir. İstediğinizi gerçekleştirmek için, giriş dizesini farklı ifadelerle birkaç kez eşleştirmeniz gerekir.

Tek bir normal ifade ile yapmak istediğiniz şey mümkün değildir .


Teknik olarak imkansız değil, ama uygulamaya değer değil. Birinin neden gerilediğini bilmiyorum ...
Robert P

13
Muhtemelen sadece mümkün olmadığı için, regex lezzetinizin bakış açılarını desteklediğini varsayarak basittir. Ve bu iyi bir bahis; günümüzün önemli programlama dillerinin çoğu bunları desteklemektedir.
Alan Moore

3

VE ifadesini normal ifadenin dışında kullanın. PHP lookahead operatörü benim için işe yaramadı, bunun yerine bunu kullandım

if( preg_match("/^.{3,}$/",$pass1) && !preg_match("/\s{1}/",$pass1))
    return true;
else
    return false;

Parola uzunluğu 3 veya daha fazla karakter ise ve parolada boşluk yoksa yukarıdaki normal ifade eşleşir.

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.