Düzenli ifadem neden X'te çalışıyor ancak Y'de çalışmıyor?


76

Belirli bir programda iyi sonuç veren düzenli bir ifade yazdım (grep, sed, awk, perl, python, yakut, ksh, bash, zsh, bul, emacs, vi, vim, gedit,…). Ancak farklı bir programda (veya farklı bir unix varyantında) kullandığımda, eşleşmeyi durduruyor. Neden?

Yanıtlar:


102

Ne yazık ki, tarihsel nedenlerden dolayı, farklı araçlar biraz farklı düzenli ifade sözdizimine sahiptir ve bazen bazı uygulamaların diğer araçlar tarafından desteklenmeyen uzantıları vardır. Ortak bir zemin olsa da, her araç yazarının farklı seçimler yapmış gibi görünüyor.

Sonuç olarak, bir araçta çalışan düzenli bir ifadeniz varsa, başka bir araçta çalışmak için değiştirmeniz gerekebilir. Yaygın araçlar arasındaki ana farklar:

  • operatörlerin +?|(){}ters eğik çizgi gerektirip gerektirmediği;
  • hangi uzantıların temellerin ötesinde .[]*^$ve genellikle+?|()

Bu cevapta ana standartları listeliyorum . Ayrıntılar için kullandığınız araçların belgelerine bakın.

Wikipedia'nın düzenli ifade motorlarını karşılaştırması, genel uygulamaların desteklediği özellikleri listeleyen bir tabloya sahiptir.

Temel düzenli ifadeler (BRE)

Temel düzenli ifadeler POSIX standardı tarafından kodlanmıştır . Bu tarafından kullanılan sözdizimi grep, sedve vi. Bu sözdizimi aşağıdaki özellikleri sunar:

  • ^ve $sadece bir satırın başında ve sonunda eşleştirin.
  • . herhangi bir karakterle (veya yeni satır hariç herhangi bir karakterle) eşleşir.
  • […]parantez içinde listelenen herhangi bir karakterle eşleşir (karakter takımı). Açma braketinden sonraki ilk karakter a ise ^, listelenmeyen karakterler yerine eşleştirilir. A eklemek için ], açılıştan hemen sonra [(veya [^negatif bir küme ise) koyun. Eğer -iki karakter arasında, bir dizi anlamına gelir; değişmezi dahil etmek için -, bir aralık olarak ayrıştırılamadığı bir yere koyun.
  • ^$.*\[Bir sonraki karakterdeki herhangi bir alıntıdan önce ters eğik çizgi .
  • * önceki karakter veya alt ifade 0, 1 veya daha fazla kez eşleşir.
  • \(…\)*Operatör veya geri referanslar ve \DIGITdeğiştirmeler ile birlikte kullanmak için sözdizimsel bir gruptur .
  • Geri referanslar \1,, \2… karşılık gelen grupla eşleşen tam metni eşleştirir, örneğin \(fo*\)\(ba*\)\1eşleşir foobaafooancak eşleşmez foobaafo. 10. gruba ve ötesine atıfta bulunmanın standart bir yolu yoktur ( \10bunun ilk anlamı standart olan a'yı izler 0).

Aşağıdaki özellikler de standart ancak bazı kısıtlı uygulamalardan eksik:

  • \{m,n\}önceki karakteri veya alt ifadeyi m ila n kere arasında eşleştirir ; n veya m ihmal edilebilir ve tam olarak m anlamına gelir .\{m\}
  • Parantezlerin içinde karakter sınıfları kullanılabilir, örneğin [[:alpha:]]herhangi bir harfle eşleşir. Parantez ifadelerinin modern uygulamaları ) aynı zamanda benzer harmanlama elemanlarını[.ll.] ve benzerlik sınıflarını içerir [=a=].

Aşağıdakiler yaygın uzantılardır (özellikle GNU araçlarında), ancak tüm uygulamalarda bulunmazlar. Kullanmakta olduğunuz aletin kılavuzuna bakın.

  • \|değişim için: veya ile foo\|bareşleşir .foobar
  • \?(kısa için \{0,1\}) ve \+(kısa için \{1,\}), bir önceki karaktere veya alt ifadeye en çok 1 veya en az 1 kez eşleşir.
  • \nyeni bir satırla \teşleşir, bir sekmeyle eşleşir vb.
  • \wHerhangi bir kelime bileşeniyle eşleşir ( [_[:alnum:]]yerelleştirme söz konusu olduğunda kısa ama bununla birlikte değişkenlik gösterir) ve \Wbir kelime bileşeni olmayan herhangi bir karakterle eşleşir.
  • \<ve \>boş dizgiyi sırasıyla kelimenin başında veya sonunda eşleştirin; \bikisiyle de eşleşir ve \Beşleşmeyenlerle eşleşir \b.

\|Operatörsüz araçların normal ifadelerin tam gücüne sahip olmadığını unutmayın. Geri referanslar, matematiksel anlamda düzenli ifadelerle yapılamayan bazı ekstra şeylere izin verir.

Genişletilmiş normal ifadeler (ERE)

Genişletilmiş düzenli ifadeler POSIX standardı tarafından kodlanmıştır . BRE'ye göre en büyük avantajları düzenliliktir: tüm standart operatörler noktalama karakterleridir, noktalama karakterlerinden her zaman alıntı yapmadan önce bir ters eğik çizgi vardır. Bu tarafından kullanılan sözdizimi awk, grep -Eya egrep, GNU sed -rve bash en=~ operatörü. Bu sözdizimi aşağıdaki özellikleri sunar:

  • ^ve $sadece bir satırın başında ve sonunda eşleştirin.
  • . herhangi bir karakterle (veya yeni satır hariç herhangi bir karakterle) eşleşir.
  • […]parantez içinde listelenen herhangi bir karakterle eşleşir (karakter takımı). İlk ^ve aralıklarla yapılan tamamlama , BRE'deki gibi çalışır (yukarıya bakın). Karakter sınıfları kullanılabilir, ancak birkaç uygulamada eksik. Modern uygulamalar aynı zamanda denklik sınıflarını ve harmanlama öğelerini de destekler. Köşeli parantez içindeki ters eğik çizgi bir sonraki karakteri bazı uygulamalarda, ancak tüm uygulamalarda kullanır; kullanmak \\taşınabilirlik için bir ters eğik çizgi anlamına.
  • (…)bu, kullanım için *veya \DIGITdeğiştirmelerde kullanılmak üzere, sözdizimsel bir gruptur .
  • |değişim için: veya ile foo|bareşleşir .foobar
  • *, +Ve ?bir önceki karakter eşleşen veya bir kaç kez alt ifade: 0 ya da daha fazla *, 1 ya da daha fazla +, 0 veya 1 için ?.
  • Ters eğik çizgi, alfasayısal değilse bir sonraki karakteri belirtir.
  • {m,n}önceki karakteri veya alt ifadeyi m ve n zamanları arasında eşleştirir (bazı uygulamalarda yoktur); n veya m ihmal edilebilir ve tam olarak m anlamına gelir .{m}
  • BRE'deki gibi bazı yaygın uzantılar: geri referanslar (özellikle kullanabileceğiniz meşgul kutusu uygulaması dışında awk'de yoktur ); özel karakterler , vb .; kelime sınırları ve kelime bileşenleri ve …\DIGIT$0 ~ "(...)\\1"\n\t\b\B\b\B

PCRE (Perl uyumlu normal ifadeler)

PCRE, başlangıçta Perl tarafından tanıtılan ve GNU tarafından kabul edilen grep -Pve çoğu PCRE kütüphanesi aracılığıyla birçok modern araç ve programlama dili olan ERE'nin uzantılarıdır . Örneklerle güzel biçimlendirme için Perl belgelerine bakın . En son Perl sürümünün tüm özellikleri PCRE tarafından desteklenmez (örn. Perl kod çalıştırma yalnızca Perl'de desteklenir). Desteklenen özelliklerin bir özeti için PCRE kılavuzuna bakın . ERE'ye yapılan başlıca eklemeler:

  • (?:…)ele geçirmeyen bir gruptur: geri (…)referanslar için olduğu gibi , ancak sayılmaz.
  • (?=FOO)BAR(lookahead) eşleşir BAR, ancak yalnızca FOOaynı pozisyondan başlamak için bir eşleşme varsa . Bu, bir eşleşmeyi aşağıdaki metni dahil etmeden tutturmak için kullanışlıdır: foo(?=bar)eşleşmeler fooancak yalnızca takip ettiği takdirde bar.
  • (?!FOO)BAR(negatif bakış açısı) eşleşir BAR, ancak FOOaynı konumda bir eşleşme de yoktur . Örneğin (?!foo)[a-z]+, başlamayan herhangi bir küçük kelimeyle eşleşir foo; [a-z]+(?![0-9)Bir sayı gelmez herhangi küçük bir sözcükle eşleşen (şimdiye içinde foo123, bu maçları fodeğil foo).
  • (?<=FOO)BAR(lookbehind) eşleşir BAR, ancak hemen için bir eşleşme öncesinde geldiyse FOO. FOOBilinen bir uzunluğa sahip olması gerekir (gibi tekrarlama operatörlerini kullanamazsınız *). Bu, eşleşmeye önceki metni dahil etmeden eşleştirmeyi bağlamak için yararlıdır: (?<=^| )fooeşleşir fooancak önce bir boşluk veya dizgenin başından önce geldiyse eşleşir .
  • (?<!FOO)BAR(negatif gözbebeği) eşleşir BAR, ancak hemen eşleşmesinden önce gelmemişse FOO. FOOBilinen bir uzunluğa sahip olması gerekir (gibi tekrarlama operatörlerini kullanamazsınız *). Bu, eşleşmeye önceki metni dahil etmeden eşleştirmeyi bağlamak için yararlıdır: (?<![a-z])fooeşleşir, fooancak yalnızca küçük harfle yazılmamışsa eşleşir .

Emacs

Emacs'in sözdizimi BRE ve ERE arasında orta düzeydedir. Emac’lara ek olarak -regexGNU find’in varsayılan sözdizimidir . Emacs aşağıdaki operatörleri sunar:

  • ^, $, ., […], *, +, ?ERE olarak
  • \(…\), \|, \{…\}, BRE olarak\DIGIT
  • daha fazla ters eğik çizgi mektubu dizileri ; \<ve \>kelime sınırları için; ve Emacs'ın son sürümlerinde, genellikle Emacs benzeri bir sözdizimine sahip diğer motorlarda desteklenmez.

Kabuk globs

Shell globs (joker karakterler) normal ifadelerden tamamen farklı ve daha az güçlü olan bir sözdizimi ile desen eşleştirmesi gerçekleştirir. Kabuklara ek olarak, bu joker karakterler find -namersync filtreleri gibi diğer araçlarla da kullanılabilir . POSIX desenleri aşağıdaki özellikleri içerir:

  • ? herhangi bir tek karakterle eşleşir.
  • […]normal düzenli ifade sözdizimlerinde olduğu gibi ayarlanmış bir karakterdir. Bazı kabuklar karakter sınıflarını desteklemez. Bazı mermiler seti olumsuzlamak !yerine gerektirir ^.
  • *herhangi bir karakter dizisi ile eşleşen (genellikle haricinde /dosya yollarını eşleşen ne olursa /dışlanan *sonra, **bazen içerir /, ancak aracın belgelerine bakın).
  • Ters eğik çizgi sonraki karakteri tırnak.

Ksh, normal ifadelerin tam gücüyle eşleşen desenini veren ek özellikler sunar . Bu özellikler çalıştırdıktan sonra bash olarak da mevcuttur shopt -s extglob. Zsh farklı bir sözdizimine sahiptir, ancak daha sonra ksh'ın sözdizimini de destekleyebilir setopt ksh_glob.


Bahsetmek isteyebileceğiniz diğer zenginvim RE'ler , 's' ve '' AT '' ve '' libast '' lardır ksh93.
Stéphane Chazelas

@ StéphaneChazelas vim dışında, vim regexps hangi programı kullanıyor? Ksh dışında hangi program libast kullanıyor?
Gilles

AT & T aracı setinin tüm AT & T RE'lerı (kullanır grep, tw, expr...). Bunun dışında ksh, bu araç seti nadiren AT&T dışında bulunur.
Stéphane Chazelas

Anlayışıma göre (ve Wikipedia'nın), "Karakter sınıfı" terimi aslında "POSIX karakter sınıfı" anlamına geliyor ... ancak, regex(7)sizinle aynı fikirde ve [these]"parantez ifadeleri" ve ("parantez ifadeleri" içinde) [:these:]"karakter sınıfları " adını veriyor . Bununla nasıl başa çıkacağımı bilemiyorum.
Adam Katz

Onlara ne diyorsanız, aralıkları destekliyorlar. Kesinlikle dikkati çekiyor -aralığını belirten ve ya (opsiyonel sonra ilk kaçmış edilmelidir ^tam anlamıyla alınacak ise) ya da son. (Ben mesela kaynaklanan hataların bol gördüğümüz [A-z]kodları 122 65 ve yanlışlıkla ait karakterleri ile eşleşen vakadan- içinde -NOT değişim, her içerir: [\]^_`. Ben de geçerli hala karışık gördüğüm [!-~]ANSI yazdırılabilir tüm karakterleri eşleştirmek için [\x21-\x7e]Farklı bir boyutta kafa karıştırsa da, eyleminde en azından basit olanı olarak görmeyi tercih ediyorum .)
Adam Katz
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.