Normal ifade ile nasıl "ters eşleşme" yapılır?


112

RegexBuddy kullanıyorum ama yine de şu şeyle başım belada: \

Satır satır bir dosya işliyorum. İstediğim şeye uygun bir "çizgi modeli" oluşturdum.

Şimdi ters eşleme yapmak istiyorum ... yani 6 harflik bir dizinin olduğu satırları eşleştirmek istiyorum, ancak bu altı harf Andrea değilse , bunu nasıl yapmalıyım?


DÜZENLEME: Bu regex'i kullanan programı yazacağım, henüz python veya php'de olup olmadığını bilmiyorum, bunu önce bazı regex öğrenmek için yapıyorum :) Farklı satır türleri var, regex kullanmak istedim İlgilendiğim türü seçmek için. Bu satırları aldıktan sonra, bilinen bir değerle eşleşmeyen başka bir filtre uygulamalıyım, diğerlerine ihtiyacım var, buna değil. (?! Aranmayan) oldukça iyi çalışıyor, teşekkürler. :-)

Umarım bu soruya açıklık getirir :)


Aslında bize ne yaptığınız hakkında biraz daha fazla bilgi vermeniz ve birinin alternatif bir çözüm sunup sunamayacağına bakmanız daha iyi gibi görünüyor. Tipik olarak, her satıra uyan bir düzenli ifade oluşturarak dosyanın tamamını ayrıştırmaya çalışmak oldukça karmaşık bir yoldur :)
Dan

Yanıtlar:


70
(?!Andrea).{6}

Normal ifade motorunuzun negatif ön yüzleri desteklediğini varsayarsak ..

Düzenleme: ..ya belki kullanmayı tercih ediyorum [A-Za-z]{6}yerine.{6}

Düzenleme (tekrar): İleriye bakmanın ve arkaya bakmanın genellikle bir normal ifade eşleşmesini "ters çevirmek" için doğru yol olmadığını unutmayın. Normal ifadeler negatif eşleme yapmak için gerçekten ayarlanmamışlardır, bunu kullandığınız dilde bırakırlar.


@Vinko Vrsalovic'in kullandığı ^ işaretini "ndrea \ n" ile
eşleşmemesi için eklemelisiniz

2
. varsayılan olarak \ n eşleşmez (bazı diller [örneğin Perl] bu davranışı açmanıza izin verir, ancak varsayılan olarak. her şeyle eşleşir ANCAK \ n).
Dan

1
(artı, OP dizenin satırın başında olması gerektiğinden hiç bahsetmedi)
Dan

1
OP için ne demek istiyorsun?
Andrea Ambu

1
Andrea: OP "orijinal poster" anlamına geliyor, bu yüzden sizden bahsediyordum :)
Dan

47

Python / Java için,

^(.(?!(some text)))*$

http://www.lisnichenko.com/articles/javapython-inverse-regex.html


4
Bu çalışmıyor. Tempered Greedy Token deyimini düşünüyorsunuz. ancak noktanın önden sonra gitmesi gerekir , önce değil. Bu soruya bakın . Ancak bu yaklaşım zaten bu görev için fazla abartılı.
Alan Moore

Hangi dilde yazıldığını bilmiyorum, ancak Sublime metninde test verilerimi temizlemek için bir cazibe gibi çalıştı. Teşekkürler!
Matthias dirickx

1
@AlanMoore Aslında, bu kullanım durumu için neredeyse işe yarayacak. Ancak, some textsatır başlarsa, yanlış sonucu döndürür.
Zenexer

2
@ Zenexer, demek istediğim buydu. Nokta öncekinden ziyade önden sonraysa, mükemmel şekilde çalışır.
Alan Moore

İşte daha fazlasını açıklayan bir bağlantı . Nedenini anlamıyorum ?!ve sadece değil !.
Timo

21

Alan Moore'un geri bildirimleriyle güncellendi

PCRE ve benzer varyantlarda, aslında değer içermeyen herhangi bir satırla eşleşen bir normal ifade oluşturabilirsiniz:

^(?:(?!Andrea).)*$

Buna sert açgözlü belirteç denir . Olumsuz yanı, iyi performans göstermemesidir.


1
Bu, uzun formdaki Tempered Greedy Token'dir. Sadece (veya nokta koymak [\s\S]ikinci lookahead sonra JavaScript olarak faydalıdır,) ve ilkini gerekmez: ^(?:(?!Andrea).)*$.
Alan Moore

@AlanMoore Güzel! Böyle çalışan herhangi bir yerleşik kalıp bulamadım, bu yüzden kendiminkini buldum. Cevabınızı almaktansa, kendi cevabınız olarak vermelisiniz.
Zenexer

Sorun değil, zaten pek çok iyi cevap var. Ve deyimi kendi başınıza icat ettiğiniz için övgüyü hak ediyorsunuz. Şerefe!
Alan Moore

Neden kullanmayı öneriyorsun [\S\s]? OP, "Andrea" kelimesini içermeyen, eşleşen çizgilerden bahsediyor. Tüm dizenin bu kelimeyi içerip içermediğini kontrol etmekle ilgili değil. Bir şey mi kaçırıyorum?
x-yuri

@ x-yuri Haklı olduğunu düşünüyorum. Muhtemelen sorduğum soruyu, tutarsızlığı görmezden gelerek, bu sayfayı ilk ziyaret ettim. Bağlantım şu anda cevabı güncellemek için yeterince iyi değil (<10 kbps)
Zenexer

11

Hangi dili kullanıyorsun Bunun için regex uygulamasının yetenekleri ve sözdizimi önemlidir.

İleriye bakmayı kullanabilirsiniz. Örnek olarak python kullanmak

import re

not_andrea = re.compile('(?!Andrea)\w{6}', re.IGNORECASE)

Bunu yıkmak için:

(?! Andrea) 'sonraki 6 karakter "Andrea" değilse eşleştir' anlamına gelir; öyleyse o zaman

\ w bir "kelime karakteri" anlamına gelir - alfanümerik karakterler. Bu, [a-zA-Z0-9_] sınıfına eşdeğerdir

\ w {6} tam olarak 6 kelime karakteri anlamına gelir.

re.IGNORECASE "Andrea", "andrea", "ANDREA" hariç tutacağınız anlamına gelir ...

Başka bir yol da program mantığınızı kullanmaktır - Andrea ile eşleşmeyen tüm satırları kullanın ve 6 karakteri kontrol etmek için ikinci bir normal ifadeden geçirin. Veya önce en az 6 kelime karakteri kontrol edin ve ardından Andrea ile eşleşip eşleşmediğini kontrol edin.


7

Negatif önden okuma iddiası

(?!Andrea)

Bu tam olarak tersine çevrilmiş bir eşleşme değildir, ancak doğrudan regex ile yapabileceğiniz en iyisidir. Yine de tüm platformlar onları desteklemez.


1
Soruyu soran kişi açıklığa kavuşturana kadar, maçın satırın başında başlaması gerektiğini görmüyorum. Peki neden ^?
Hamish Downer

Hattın başında kontrol etmek istediğini anladığım için açıklamalara göre düzenlendi
Vinko Vrsalovic

5

Bunu RegexBuddy'de yapmak istiyorsanız, bir normal ifadeyle eşleşmeyen tüm satırların bir listesini almanın iki yolu vardır.

Test panelindeki araç çubuğunda, test kapsamını "Satır satır" olarak ayarlayın. Bunu yaptığınızda, Eşleşmeyen Tüm Satırları Listele öğesi aynı araç çubuğundaki Tümünü Listele düğmesinin altında görünecektir. (Tümünü Listele düğmesini görmüyorsanız, ana araç çubuğundaki Eşleştir düğmesini tıklayın.)

GREP panelinde, içinden geçtiğiniz dosyalardaki eşleşmeyen satırların bir listesini almak için "satır tabanlı" ve "sonuçları ters çevir" onay kutularını açabilirsiniz.


5

(?!pratikte kullanışlıdır. Kesin olarak konuşulsa da, ileriye bakmak matematiksel olarak tanımlandığı gibi normal bir ifade değildir.

Manuel olarak ters bir normal ifade yazabilirsiniz.

İşte sonucu otomatik olarak hesaplamak için bir program . Bunun sonucu, genellikle elle yazmadan çok daha karmaşık olan makine tarafından üretilir. Ancak sonuç işe yarıyor.


1

Donanım açısından yoğun olabilecek bu yöntemi yeni buldum ama çalışıyor:

Normal ifadeyle eşleşen tüm karakterleri boş bir dizeyle değiştirebilirsiniz.

Bu bir oneliner:

notMatched = re.sub(regex, "", string)

Bunu kullandım çünkü çok karmaşık bir normal ifade kullanmak zorunda kaldım ve makul bir süre içinde her parçasını nasıl ters çevireceğimi çözemedim.

Bu size herhangi bir eşleşme nesnesini değil, yalnızca dize sonucunu döndürecektir!


-3

Perl'de yapabilirsin

süreç ($ satır) if ($ satır = ~! / Andrea /);


4
Bu sözdizimi yanlış. Sanırım işlem ($ line) $ line ise demek istiyorsun ~ / Andrea /
dland
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.