Normal ifadelerde hangi özel karakterler kaçmalı?


389

()[]{}|Normal ifadelerin birçok uygulamasını kullanırken ' ' vb. Gibi özel karakterlerden kaçmam gerekirse her zaman tahmin etmeye çalışmaktan bıktım .

Örneğin Python, sed, grep, awk, Perl, yeniden adlandır, Apache, bul vb. İle farklıdır. Özel karakterlerden ne zaman kaçmam gerektiğini ve ne zaman yapmamam gerektiğini söyleyen bir kural seti var mı? PCRE, POSIX veya genişletilmiş normal ifadeler gibi normal ifade türüne bağlı mı?


4
Normal regex kütüphaneleri, normal escape()dizelerin regex parçaları olarak kullanılmasına izin vermek için " " gibi işlevlere sahiptir .
ivan_pozdeev

2
Gskinner.com/RegExr (ücretsiz) gibi çevrimiçi Regex ifade denetleyicilerini kullanabilirsiniz . (
Yazıp

2
Alfasayısal olmayan tüm karakterlerden kaçın. dönem.
Salman von Abbas

2
Bu soru "Diğer" altında Yığın Taşması Düzenli İfade SSS'ye eklenmiştir .
aliteralmind

1
Bu soru, "Çıkış Dizileri" altında Yığın Taşması Düzenli İfade SSS'ye eklenmiştir .
aliteralmind

Yanıtlar:


365

Hangi karakterlere sahip olmanız ve hangi karakterlerden kaçmamanız gerektiği, üzerinde çalıştığınız normal ifade lezzetine bağlıdır.

PCRE ve diğer Perl uyumlu lezzetler için bu dış karakter sınıflarından kaçın:

.^$*+?()[{\|

ve bu karakter sınıflarının içinde:

^-]\

POSIX genişletilmiş normal ifadeleri (ERE) için bu dış karakter sınıflarından (PCRE ile aynı) kaçın:

.^$*+?()[{\|

Başka karakterlerden kaçmak POSIX ERE ile ilgili bir hatadır.

Karakter sınıflarının içinde ters eğik çizgi, POSIX normal ifadelerinde gerçek bir karakterdir. Hiçbir şeyden kaçmak için kullanamazsınız. Karakter sınıfı metakarakterlerini değişmez olarak eklemek istiyorsanız "akıllı yerleşim" kullanmanız gerekir. ^ Başlangıcında, başlangıcında] ve karakter sınıfının başlangıcında veya sonunda, kelimenin tam anlamıyla eşleşmesi için - herhangi bir yere koyun, örneğin:

[]^-]

POSIX temel düzenli ifadelerinde (BRE), bunlar anlamlarını bastırmak için kaçmanız gereken meta karakterlerdir:

.^$*[\

BRE'lerde kaçan parantezler ve süslü parantezler onlara kaçmayan sürümlerinin ERE'lerde sahip olduğu özel anlamı verir. Bazı uygulamalar (örn. GNU), kaçıldığında \? Gibi diğer karakterlere de özel bir anlam verir. ve +. . ^ $ * () {} Dışında bir karakterden kaçmak normalde BRE'lerde bir hatadır.

Karakter sınıflarının içinde, BRE'ler ERE'lerle aynı kuralı izler.

Bütün bunlar başınızı döndürürse, RegexBuddy'nin bir kopyasını alın . Oluştur sekmesinde, Simge Ekle'yi ve ardından Değişmez'i tıklatın. RegexBuddy gerektiğinde kaçışlar ekleyecektir.


1
Bana öyle geliyor ki, bir sınıfın dışında kaçması gereken "/" yi de unuttun.
jackthehipster

11
/bahsettiğim normal ifade tatlarının hiçbirinde bir metakarakter değildir, bu yüzden düzenli ifade sözdiziminin kaçmasını gerektirmez. Normal ifade o dilin dize veya düzenli ifade biçimlendirme kuralları gerektirebilir, bir programlama dilinde bir hazır olarak aktardığı zaman /ya "ya '\ `kaçmış olması ve hatta gerektirebilir` çifte çıkış yapılmasını.
Jan Goyvaerts

2
iki nokta üst üste, ":"? Karakter sınıflarının içinde ve dışında kaçabilir mi? en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions "PCRE tutarlı kaçan kuralları vardır: Herhangi olmayan alfa-sayısal karakter onun değişmez değerini [...] anlamında çıkışı yapılabilir" diyor
nicolallias

4
Kaçabilir MAYIS kaçması ile aynı değildir. PCRE sözdizimi hiçbir zaman değişmez bir kolonun kaçmasını gerektirmez, bu nedenle kaçan değişmez sütunlar normal ifadenizi yalnızca okumayı zorlaştırır.
Jan Goyvaerts

1
POSIX olmayan ERE için (Tcl tarafından uygulanan şey olduğu için en sık kullandığım) diğer şeylerden kaçmak hata oluşturmaz.
slebetman

61

Modern RegEx Aromaları (PCRE)

C, C ++, Delphi, EditPad, Java, JavaScript, Perl, PHP (preg), PostgreSQL, PowerGREP, PowerShell, Python, REALbasic, Real Studio, Ruby, TCL, VB.Net, VBScript, wxWidgets, XML Şeması, Xojo, XRegExp.
PCRE uyumluluğu değişiklik gösterebilir

    Herhangi bir yer: . ^ $ * + - ? ( ) [ ] { } \ |


Eski RegEx Aromaları (BRE / ERE)

Awk, ed, egrep, emacs, GNUlib, grep, PHP (ereg), MySQL, Oracle, R, sed içerir.
PCRE desteği sonraki sürümlerde veya uzantılar kullanılarak etkinleştirilebilir

ERE / awk / egrep / emacs

    Bir karakter sınıfının dışında: . ^ $ * + ? ( ) [ { } \ |
    Bir karakter sınıfının içinde:^ - [ ]

BRE / ed / grep / sed

    Karakter sınıfının dışında: . ^ $ * [ \
    Karakter sınıfının içinde: ^ - [ ]
    Değişmez değerler için kaçmayın: + ? ( ) { } |
    Standart normal ifade davranışı için kaçış:\+ \? \( \) \{ \} \|


notlar

  • Belirli bir karakterden emin değilseniz, aşağıdaki gibi kaçabilir \xFF
  • Alfasayısal karakterler ters eğik çizgi ile kaçamaz
  • Keyfi semboller PCRE'de ters eğik çizgi ile kaçabilir, ancak BRE / ERE ile kaçamazlar (yalnızca gerektiğinde kaçmalıdırlar). PCRE için ] -sadece bir karakter sınıfından kaçmak gerekiyor, ancak basitlik için onları tek bir listede tuttum
  • Alıntı ifade dizeleri de karakterlerin çıkış çevreleyen alıntı olmalı ve sık sık ters eğik çizgi ile iki büklüm olmuş (gibi "(\")(/)(\\.)"karşı /(")(\/)(\.)/JavaScript)
  • Kaçışların yanı sıra, farklı regex uygulamaları farklı değiştiricileri, karakter sınıflarını, çapaları, niceleyicileri ve diğer özellikleri destekleyebilir. Daha fazla ayrıntı için kontrol regular-expressions.info veya kullanmak regex101.com da ifadeleri canlı test etmek

1
Senin "modern" tatlar hiçbiri gerektiren: sınırlı sayıda Cevabınız hatalar dahil ancak vardır -ya ]dış karakter sınıfları kurtuldu edilecek. POSIX'in (BRE / ERE) karakter sınıflarının içinde kaçış karakteri yoktur. Delphi'nin RTL'sindeki normal ifade aroması aslında PCRE'ye dayanıyor. Python, Ruby ve XML, PCRE'ye POSIX lezzetlerinden daha yakın olan kendi lezzetlerine sahiptir.
Jan Goyvaerts

1
@ JanGoyvaerts Düzeltme için teşekkürler. Bahsettiğiniz lezzetler gerçekten PCRE'ye daha yakın. Kaçışlara gelince, basitlik için onları böyle tuttum; birkaç istisna dışında her yerden kaçmayı hatırlamak daha kolaydır. Uzman kullanıcılar, birkaç ters eğik çizgiden kaçınmak istediklerini bilir. Her neyse, cevabımı bu konuların bazılarına hitap eden birkaç açıklama ile güncelledim.
Beejor

22

Ne yazık ki, kullandığınız dile göre değiştiği için gerçekten bir kaçış kodu seti yoktur.

Ancak, Normal İfade Araçları Sayfası veya bu Normal İfade Cheatsheet gibi bir sayfanın tutulması, şeyleri hızlı bir şekilde filtrelemenize yardımcı olmak için uzun bir yol kat edebilir.


1
Addedbytes hile sayfası aşırı derecede basitleştirilmiştir ve bazı göze çarpan hatalar vardır. Örneğin , Boost normal ifadesi kütüphanesinde yalnızca doğru olan (AFAIK) sözcük sınırları diyor \<ve \>bunlar. Ama başka bir yerde diyor <ve >metakta karakter ve onları tam anlamıyla eşleştirmek için kaçmak ( \<ve \>), herhangi bir lezzet doğru değil
Alan Moore

5

Ne yazık ki, (ve \ () gibi şeylerin anlamı Emacs stili düzenli ifadeler ve diğer birçok stil arasında değişiyor. Yani bunlardan kaçmaya çalışırsanız, istediğiniz şeyin tersini yapıyor olabilirsiniz.

Yani hangi stili teklif etmeye çalıştığınızı gerçekten bilmelisiniz.


5

POSIX normal ifadelerde birden çok varyasyonu tanır - temel düzenli ifadeler (BRE) ve genişletilmiş düzenli ifadeler (ERE). Ve o zaman bile, POSIX tarafından standartlaştırılan yardımcı programların tarihsel uygulamaları nedeniyle tuhaflıklar var.

Hangi gösterimin ne zaman kullanılacağına, hatta belirli bir komutun hangi gösterimi kullandığına dair basit bir kural yoktur.

Jeff Friedl'in Mastering Regular Expressions kitabına göz atın .


4

Gerçekten yok. yaklaşık yarım milyon farklı regex sözdizimi vardır; genel olarak Perl, EMACS / GNU ve AT&T'ye geliyorlar ama ben de her zaman şaşırıyorum.


4

Bazen listelediğiniz karakterlerle basit bir kaçış mümkün değildir. Örneğin, köşeli ayraçtan kaçmak için ters eğik çizgi kullanmak sed'deki bir ikame dizesinin sol tarafında, yani

sed -e 's/foo\(bar/something_else/'

Bunun yerine sadece basit bir karakter sınıfı tanımı kullanma eğilimindeyim, bu yüzden yukarıdaki ifade

sed -e 's/foo[(]bar/something_else/'

çoğu regexp uygulaması için işler buluyorum.

BTW Karakter sınıfları oldukça vanilya regexp bileşenleridir, bu nedenle normal ifadelerde kaçan karakterlere ihtiyaç duyduğunuz çoğu durumda çalışma eğilimindedirler.

Düzenleme: Aşağıdaki yorumdan sonra, ben sadece regexp değerlendirme davranışı bakarken sonlu durum otomata ve sonlu olmayan otomata arasındaki farkı dikkate almak zorunda olduğunu söyledi düşündüm.

Regexp motor değerlendirme türlerindeki farkı anlamak için "parlak top kitabına" aka Etkili Perl'e ( sterilize edilmiş Amazon bağlantısı ), özellikle düzenli ifadeler bölümüne bakmak isteyebilirsiniz .

Tüm dünya PCRE değil!

Her neyse, regexp'ler SNOBOL ile karşılaştırıldığında çok hantal ! Şimdi bu ilginç bir programlama dersiydi! Üzerinde biriyle birlikte Simula .

Ah, 70'lerin sonunda UNSW'de okumaktan keyif alıyor! (-:


'sed' düz '(' özel değil ama '\ (' özeldir; aksine PCRE duyguyu tersine çevirir, bu yüzden '(' özeldir, ancak '\ (' değildir.) OP soruyor
Jonathan Leffler

sed regexp değerlendirmesinin en ilkel kümelerinden birini kullanan bir * nix yardımcı programıdır. PCRE, regexps'i değerlendirme şekliyle farklı bir (in) sonlu otomata sınıfı içerdiğinden, tanımladığım duruma girmez. Bence regexp sözdizimi için benim önerim hala geçerli.
Rob Wells

1
POSIX uyumlu bir sistemde sed, cevabımda ele aldığım POSIX BRE kullanıyor. Modern Linux sistemindeki GNU sürümü birkaç uzantı ile POSIX BRE kullanır.
Jan Goyvaerts

2

PHP için "alfasayısal olmayan bir öğenin önüne" \ "işareti koymak onun için olduğunu belirtmek her zaman güvenlidir." - http://php.net/manual/en/regexp.reference.escape.php .

"Veya" olması dışında.: /

PHP'de normal ifade kalıbı değişkenlerinden (veya kısmi değişkenlerinden) kaçmak için preg_quote () kullanın


2

Denemeden ne zaman ve ne kaçması gerektiğini bilmek, ipin içinden geçtiği bağlam zincirini tam olarak anlamak için gereklidir. Dizgiyi en uzak taraftan, regexp ayrıştırma kodu tarafından işlenen bellek olan son hedefine kadar belirlersiniz.

Bellekteki dizenin nasıl işlendiğine dikkat edin: kodun içinde düz bir dize veya komut satırına girilen bir dize olabilir, ancak bir etkileşimli komut satırı veya kabuk komut dosyası içinde belirtilen bir komut satırı olabilir veya kodda belirtilen bellekteki bir değişkenin veya daha fazla değerlendirme yoluyla (dize) bağımsız değişkeninin veya herhangi bir kapsülleme ile dinamik olarak oluşturulan kodu içeren bir dize içinde ...

Bu bağlamın her birine özel işlevselliğe sahip bazı karakterler verilmiştir.

Karakteri, özel işlevini (bağlama özgü) kullanmadan tam anlamıyla geçirmek istediğinizde, bundan sonra, bir sonraki bağlam için, bundan başka olması gereken diğer bazı kaçış karakterlerine ihtiyaç duyabilecek olan, kaçmak zorundasınız. önceki bağlam (lar) da kaçtı. Dahası, karakter kodlama gibi şeyler olabilir (en sinsi utf-8'dir, çünkü ortak karakterler için ASCII gibi görünür, ancak ayarlarına bağlı olarak terminal tarafından bile isteğe bağlı olarak yorumlanabilir, böylece farklı davranabilir, ardından HTML'nin kodlama özelliği / XML, işlemi tam olarak anlamak gerekir.

Örneğin, komut satırında başlayan bir regexp dosyası, dosya tanıtıcılarını boru olarak bağlayan perl -npebir dizi exec sistem çağrısına aktarılmalıdır , bu exec sistem çağrılarının her birinde yalnızca (çıkışsız) boşluklarla ayrılmış argümanların bir listesi vardır, ve muhtemelen boru (|) ve yeniden yönlendirme (> N> N> ve K), parantez, etkileşimli genişlemesi *ve ?,$(())... (tüm bunlar * sh tarafından kullanılan ve bir sonraki bağlamda normal ifadenin karakterine müdahale ettiği anlaşılan özel karakterlerdir, ancak sırasıyla değerlendirilir: komut satırından önce. bash / sh / csh / tcsh / zsh olarak program, temelde çift tırnak veya tek tırnak içinde kaçış daha basittir, ancak komut satırında bir dize alıntı yapmak gerekli değildir, çünkü çoğunlukla boşluk ters eğik çizgi ile ön ekli ve tırnak işareti vardır * ve? karakterleri için genişleme işlevselliğini bırakmak gerekli değildir, ancak alıntı içinde olduğu gibi farklı bağlamda ayrıştırılır.Ardından komut satırı değerlendirildiğinde bellekte elde edilen normal ifade (komut satırında yazıldığı gibi) aynı muameleyi alır regexp için köşeli parantezler [],perl düzenli ifadesi, büyük bir alfa-sayısal olmayan karakter kümesiyle tırnak içine alınabilir (örneğin, m // veya m: / better / for / path: ...).

Diğer cevaptaki son regexp bağlamına özgü karakterler hakkında daha fazla ayrıntı var. Belirttiğim gibi, regexp kaçışını denemelerle bulduğunuzdan bahsettiğiniz gibi, bunun nedeni muhtemelen farklı bağlamın girişimlerinizi karıştıran farklı bir karakter kümesine sahip olmasıdır (genellikle ters eğik çizgi, işlevi yerine değişmez bir karakterden kaçmak için bu farklı bağlamda kullanılan karakterdir ).



0

İyonik (Daktilo Yazısı) için karakterleri değiştirmek için çift eğik çizgi yapmanız gerekir. Örneğin (bu, bazı özel karakterlerle eşleşmelidir):

"^(?=.*[\\]\\[!¡\'=ªº\\-\\_ç@#$%^&*(),;\\.?\":{}|<>\+\\/])"

Bu ] [ - _ . /karakterlere dikkat edin . Çift kesik kesilmeleri gerekiyor. Bunu yapmazsanız, kodunuzda bir tür hatası olacaktır.

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.