Düzenli ifadeler neden bu kadar tartışmalı? [kapalı]


212

Düzenli ifadeleri (başka bir deyişle RegEx-es olarak bilinir) keşfederken, düzenli ifadeleri Kutsal Kâse olarak gören birçok kişi vardır. Çok karmaşık görünen bir şey - herhangi bir sorunun cevabı olmalı. Her sorunun düzenli ifadeler kullanılarak çözülebileceğini düşünüyorlar.

Öte yandan, düzenli ifadelerden kaçınmaya çalışan birçok insan da var. Düzenli ifadeler etrafında bir yol bulmaya çalışırlar ve düzenli ifadeler daha kompakt bir çözüm olsa bile, sadece uğruna ek kodlamayı kabul ederler.

Düzenli ifadeler neden bu kadar tartışmalı kabul ediliyor? Nasıl çalıştıklarına dair yaygın yanlış anlaşılmalar var mı? Yoksa düzenli ifadelerin genellikle yavaş olduğuna dair geniş bir inanç olabilir mi?


9
bu bir tartışma ise, kapatılmamalı mı? ama orada gerçek bir soru görüyorum belki tartışma etiketi ait değil mi?
RCIX

6
Şaka yapmıyorum. Siz getirin ve insanlar burada çıldırmaya başlar.
Ryan Florence

1
Soruda güzel gözlem ve ifadeler!
imz - Ivan Zakharyaschev


Soru, kuralın burada da uygulanması gereken görüşe dayalıdır (veya soru kesin bir cevabı hedeflemek için düzenlenmelidir). Regex ihtilafının bu konuda öğreticilerin ve kılavuzların hassasiyetinden geldiğini varsayıyorum. Çoğu zaman her zaman bilgi karışık değilse ve ek olarak bize tüm özellikler verilmez. Bu dili özledim kullanımını ekleyin, sonunda başka bir şey anlamına gelebileceğini fark etmek için bir şeyler öğreniyorsunuz. Ve son olarak özel normal ifade karakterleri daha fazla karışıklık yaratan bir anlamla sınırlı değildir.
intika

Yanıtlar:


136

İnsanların düzenli ifadelere karşı çıkmadıklarını düşünmüyorum, çünkü yavaşlar, ama okumak ve yazmak zor olduğu için doğru olmak zor. Düzenli ifadelerin soruna etkili ve kompakt bir çözüm sağladığı bazı durumlar olsa da, bazen okunması kolay, bakımı kolay bir kod bölümü kullanmanın daha iyi olduğu durumlara atılırlar.


2
Ve evet, normal ifadeler basit işlevleri kullanmaya kıyasla son derece yavaş olabilir. Ve sadece yavaş değil, regex motorunun performansı, rastgele (kullanıcı tarafından sağlanan) girişlerle karşı karşıya kaldığında tamamen tahmin edilemez olabilir .
Pacerier

1
Normal ifadenin nasıl çalıştığını biliyorsanız, hiç sorun değil.
Shiplu Mokaddim

8
@pacerier, yavaş kalıplar değil , yavaş motorlar . Çoğu (modern) düzenli ifade motoru karmaşık modeller için uygun değildir (örn. Birçok |veya .*), çünkü bir yığın makinesi ve geri izleme kullanırlar. Bu yüzden Perl, Java, Python, Ruby'deki düzenli ifadelerinizi dikkatlice ayarlamanız gerekir. Eski tarz düzenli ifade motorları ( grepörneğin,) önce deseni bir DFA'ya derler. Daha sonra, desenin karmaşıklığı büyük ölçüde ilgisizdir. Ben sadece aynı metin ve desen için Java ve grep kullandım: 22min vs 2s. İşte bilim: swtch.com/~rsc/regexp/regexp1.html
hagello

122

Regexes'i Bakım Yapabilme

Daha önce “düzenli ifadeler” olarak adlandırılan örüntüleri belirsizleştirmeye yönelik büyük bir ilerleme Perl's /x bazen (?x)gömüldüğünde yazılan ve boşluk (satır kesmesi, girintileme) ve yorumlara izin veren işaretidir. Bu, okunabilirliği ve dolayısıyla sürdürülebilirliği ciddi şekilde geliştirir. Beyaz boşluk bilişsel parçalamaya izin verir, böylece hangi grupların neyle birlikte olduğunu görebilirsiniz.

Modern kalıplar artık hem nispeten sayılı hem de adlandırılmış geri başvuruları desteklemektedir. Bu, ihtiyacınız olduğunu anlamak için artık yakalama gruplarını saymanıza gerek olmadığı anlamına gelir$4 veya \7. Bu, diğer kalıplara eklenebilecek kalıplar oluştururken yardımcı olur.

Göreceli olarak numaralandırılmış bir yakalama grubuna örnek:

$ dupword = qr {\ b (?: (\ w +) (?: \ s + \ g {-1}) +) \ b} xi;
$ quoted = qr {(["']) $ dupword \ 1} x;

Ve burada adlandırılmış yakalamaların üstün yaklaşımının bir örneği:

$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted  = qr{ (?<quote> ["'] ) $dupword  \g{quote} }x;

Dilbilgisel Düzenlemeler

Hepsinden iyisi , bu adlandırılmış yakalamalar bir (?(DEFINE)...)blok içine yerleştirilebilir , böylece bildirimi kalıplarınızın tek tek adlandırılmış öğelerinin yürütülmesinden ayırabilirsiniz. Bu onları kalıptaki alt rutinler gibi hareket ettirir.
Bu tür “dilbilgisel regex” in iyi bir örneği bu cevapta ve bu cevapta bulunabilir . Bunlar daha çok gramer bildirisine benziyor.

İkincisinin size hatırlattığı gibi:

… Hiçbir zaman çizgi gürültüsü kalıpları yazmadığınızdan emin olun. Gerek yok ve gerek yok. Beyaz boşluk, yorumlar, alt rutinler veya alfasayısal tanımlayıcıları yasaklayan hiçbir programlama dili korunamaz. Öyleyse kalıplarınızdaki tüm bunları kullanın.

Bu fazla vurgulanamaz. Elbette bu şeyleri desenlerinizde kullanmazsanız, genellikle bir kabus yaratacaksınız. Eğer Ama eğer yapmak bunları kullanmak olsa da, sen gerekmez.

İşte modern bir gramer deseninin başka bir örneği, bu RFC 5322'yi ayrıştırmak için: 5.10.0 kullanın;

$rfc5322 = qr{

   (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)

}x;

Bu olağanüstü ve muhteşem değil mi? BNF tarzı bir dilbilgisi alabilir ve temel yapısını kaybetmeden doğrudan koda çevirebilirsiniz!

Modern gramer desenleri hala sizin için yeterli değilse Damian Conway'in parlak Regexp::Grammarsmodülü , daha üstün hata ayıklama ile daha da temiz bir sözdizimi sunar. RFC 5322 recast'ı bu modüldeki bir desene ayrıştırmak için aynı kod:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";

my $rfc5322 = do {
    use Regexp::Grammars;    # ...the magic is lexically scoped
    qr{

    # Keep the big stick handy, just in case...
    # <debug:on>

    # Match this...
    <address>

    # As defined by these...
    <token: address>         <mailbox> | <group>
    <token: mailbox>         <name_addr> | <addr_spec>
    <token: name_addr>       <display_name>? <angle_addr>
    <token: angle_addr>      <CFWS>? \< <addr_spec> \> <CFWS>?
    <token: group>           <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
    <token: display_name>    <phrase>
    <token: mailbox_list>    <[mailbox]> ** (,)

    <token: addr_spec>       <local_part> \@ <domain>
    <token: local_part>      <dot_atom> | <quoted_string>
    <token: domain>          <dot_atom> | <domain_literal>
    <token: domain_literal>  <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?

    <token: dcontent>        <dtext> | <quoted_pair>
    <token: dtext>           <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]

    <token: atext>           <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
    <token: atom>            <.CFWS>? <.atext>+ <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom_text>   <.atext>+ (?: \. <.atext>+)*

    <token: text>            [\x01-\x09\x0b\x0c\x0e-\x7f]
    <token: quoted_pair>     \\ <.text>

    <token: qtext>           <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
    <token: qcontent>        <.qtext> | <.quoted_pair>
    <token: quoted_string>   <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
                             <.FWS>? <.DQUOTE> <.CFWS>?

    <token: word>            <.atom> | <.quoted_string>
    <token: phrase>          <.word>+

    # Folding white space
    <token: FWS>             (?: <.WSP>* <.CRLF>)? <.WSP>+
    <token: ctext>           <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
    <token: ccontent>        <.ctext> | <.quoted_pair> | <.comment>
    <token: comment>         \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
    <token: CFWS>            (?: <.FWS>? <.comment>)*
                             (?: (?:<.FWS>? <.comment>) | <.FWS>)

    # No whitespace control
    <token: NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]

    <token: ALPHA>           [A-Za-z]
    <token: DIGIT>           [0-9]
    <token: CRLF>            \x0d \x0a
    <token: DQUOTE>          "
    <token: WSP>             [\x20\x09]

    }x;

};


while (my $input = <>) {
    if ($input =~ $rfc5322) {
        say Dumper \%/;       # ...the parse tree of any successful match
                              # appears in this punctuation variable
    }
}

Orada iyi bir sürü şey var perlre manpage ama temel regex tasarım özellikleri bu dramatik gelişmeler yalnız Perl ile sınırlı değillerdir. Gerçekten de pcrepattern manpage daha kolay okunabilir ve aynı bölgeyi kapsıyor olabilir.

Modern kalıpların, sonlu otomata sınıfınızda öğretilen ilkel şeylerle neredeyse hiçbir ortak yanı yoktur.


9
EVET! EVET! Son olarak, birisi x değiştiricisiyle okunabilir normal ifadelerin nasıl olabileceğine dair harika bir örnek gösterir. Aslında onu kullanmasına izin vermeden, az sayıda insanın var olduğunu bildiğine inanamıyorum.
Shabbyrobe

1
@Shabbyrobe: Sadece değil /x. Regex'leri dilbilgisel olarak kullanıyor, (?&name)iç regex altyordamlarıyla, bu gerçekten parlıyor.
tchrist

+1 Her zaman yeni bir şey öğrenirsiniz. PCRE'nin tanımlamalar için "yanlış" bir koşula sahip olduğunu bilmiyordum.
NikiC

5
Python'un da benzer bir re.VERBOSEbayrağı var.
Mekanik salyangoz

3
Sadece gunna devam edin ve normal ifadeyi kullanılabilir hale getirmek için insanların gidecekleri uzunluklara hala hayran olduğumu söyleyin.
Slater Victoroff

68

Regexes harika bir araç, ancak insanlar "Hey, ne harika bir araç, X yapmak için kullanacağım!" burada X, farklı bir aracın daha iyi olduğu bir şeydir (genellikle bir ayrıştırıcı). Bir tornavida problemine ihtiyacınız olan bir çekiç kullanarak standarttır.


4
Sadece ayrıştırıcıların çoğu -solojik analizörler- hala eşyalarını ayrıştırmak için düzenli ifadeler kullandığını unutmayın :-)
Jasper Bekkers

62
Ayrıştırıcıların düzenli ifadeler kullandığını söylemek, ayrıştırıcıların atama ifadeleri kullandığını söylemek gibidir. Nasıl kullanıldığını görene kadar hiçbir şey ifade etmiyor.
Chas. Owens

24
Bir ayrıştırıcı daha iyi olduğunda bir RegEx kullanmak sinir bozucu. Dilin standart dize bulma veya değiştirme işlevleri çalıştığında (ve genellikle doğrusal zamanda) bir RegEx kullanmak sadece affedilemez.
jmucchiello

1
Kabul etti, çünkü bir RegEx'in işlem yaptığı tüm işlemlerden bir jack olması gerekiyor, bu işlem yükü çok büyük. Bir RegEx motorunun kolay görünmesi, yinelemeli bir ayrıştırıcıya (geliştiriciye bağlı eşik) göre daha iyi bir çözüm olduğu anlamına gelmez. Benim en sevdiğim örneklerden biri PHP'nin split($pattern,$string)vs explode($delimiter,$string)- neyse ki eski amortisman oluyor, ama daha sonra sadece gücüne ihtiyaç duyduklarında çok sayıda kod eski kullanıldı. Toplam, RegEx's bazı şeyler yapmak için kolay bir araç sağlar, ancak düzenli ifadelerin tüm gücüne ihtiyacınız yoksa onlar
Rudu

4
Sözcüksel analizörler gerçekten normal ifadeler kullanabilir. Toklaştırıcılar olarak da bilinirler, ancak sözdizimsel analizörler (veya ayrıştırıcılar) değildir. Yeterince karmaşık bir dize okumak için, dizgiyi belirteç olarak okumak için bir belirteç kullanılmalıdır (belirteçlere bağlı olarak belki de regexes ile değil). Bu tokenler daha sonra bunları kesinlikle regex olmayan gramer kuralları ile işleyecek olan ayrıştırıcıya iletilmelidir.
Axel

53

Düzenli ifadeleri düzenli olarak (tanıma amaçlı) kullanan neredeyse tanıdığım herkes, RE'leri grep, sed, awk ve Perl gibi birinci sınıf programlama yapıları olarak gören araçları kullandıkları Unix-ish geçmişinden geliyor. Düzenli bir ifade kullanmak için neredeyse hiç sözdizimsel yük olmadığından, üretkenlikleri üretildiklerinde artar.

Buna karşılık, RE'lerin harici bir kütüphane olduğu dilleri kullanan programcılar, düzenli ifadelerin tabloya getirebileceği düşünme eğilimindedir. Programcı "zaman maliyeti" o kadar yüksektir ki a) RE'ler asla eğitimlerinin bir parçası olarak ortaya çıkmazlar veya b) RE'ler açısından "düşünmezler" ve daha tanıdık kalıplara geri dönmeyi tercih ederler.


11
Evet, Python'u bir kütüphane kullanarak normal ifade sözdizimini ayrıntılı yaptığı için asla affetmedim. Bence bu akıl sağlığının saflığı.
slikts

7
Unix bir arka plandan geliyorum, sed, awk ve perl yükleri kullandım ve elbette bolca selam verdiler, ama bir normal ifade kullandığımda, bakımdan nefret edeceğim sadece yazılan bir saldırı olduğunu biliyorum. Kabuk betikleri / bir zamanlayıcılar için iyidir, ancak gerçek çalışma için, sadece kaydetmek için bazı verileri yakalamayan herhangi bir şey için, şimdi açık sözdizimine sahip uygun bir tokenizer / lexer / ayrıştırıcı kullanıyorum. En sevdiğim her şeyi yapar, temiz + kendini optimize edebilir. Zor yoldan öğrendim ve uzun yıllar boyunca başlangıçta biraz öz disiplinin daha sonra daha az çaba gerektirdiğini öğrendim. Normal ifade klavyede geçen bir andır ve kaşların üzerinde bir ömürdür.
AndrewC

44

Düzenli ifadeler, bir dizi girişi işlemek için özel bir sonlu durum makinesi (FSM) yazmanızı sağlar. Normal ifadeleri kullanmanın zor olmasının en az iki nedeni vardır:

  • Eski yazılım geliştirme, çok fazla planlama, kağıt model ve dikkatli düşünmeyi içerir. Düzenli ifadeler bu modele çok iyi uyum sağlar, çünkü etkili bir ifade yazmak için FSM'nin yollarını görselleştirerek ona çok fazla bakmak gerekir.

    Modern yazılım geliştiricileri kodun daha çok kullanılmasını ve kodun doğru olup olmadığını görmek için bir hata ayıklayıcı kullanırlar. Düzenli ifadeler bu çalışma tarzını çok iyi desteklemiyor. Düzenli bir ifadenin "çalışması" etkili bir şekilde atomik bir işlemdir. Bir hata ayıklayıcıda adım adım yürütmeyi gözlemlemek zor.

  • Yanlışlıkla düşündüğünüzden daha fazla girdi kabul eden normal bir ifade yazmak çok kolaydır. Normal ifadenin değeri gerçekten geçerli girdiyle eşleşmez, geçersiz girdiyle eşleşmez . Düzenli ifadeler için "negatif testler" yapma teknikleri çok ileri değildir veya en azından yaygın olarak kullanılmamaktadır.

    Bu, düzenli ifadelerin okunması zor olan noktaya gider. Sadece düzenli bir ifadeye bakarak, reddedilmesi gereken, ancak yanlışlıkla kabul edilen tüm olası girdileri görselleştirmek çok yoğun bir konsantrasyon gerektirir. Hiç başkasının normal ifade kodunda hata ayıklamaya çalıştınız mı?

Bugün yazılım geliştiricileri arasında düzenli ifadelerin kullanılmasına karşı bir direnç varsa, bunun esas olarak bu iki faktörden kaynaklandığını düşünüyorum.



15
perl -Mre = hata ayıklama -e "q [aabbcc] = ~ / ab * [cd] /"
Brad Gilbert

15
Uçan Spagetti Canavarı'nı düşünmeden kısaltmayı "FSM" gördüğümü hiç sanmıyorum.
Shabbyrobe

4
@Shabbyrobe: Kırmak istemiyorum. İsterseniz, deterministik sonlu otomatı (DFA) kullanabilirsiniz.
Bill Karwin

37

İnsanlar düzenli ifadelerin zor olduğunu düşünüyorlar; ama bunun sebebi onları yanlış kullanıyorlar. Yorum içermeyen karmaşık tek satırlar yazma, girintiler veya adlandırılmış yakalamalar. (Karmaşık SQL ifadenizi yorum, girinti veya takma ad olmadan tek bir satırda sıkıştırmazsınız, değil mi?). Evet, birçok insan için mantıklı değil.

İşiniz varsa Ancak, herhangi bir şey (... Orada kabaca herhangi bir web uygulaması) metin ayrıştırma ile ilgisi ve düzenli ifade bilmiyorum işinizde emmek ve kendi zamanını boşa harcıyorsun ve o senin işveren. Onlar hakkında bilmeniz gereken her şeyi ve daha fazlasını öğretmek için mükemmel kaynaklar var.


2
Peki .. fark şudur ki, regex'te birden fazla alanın anlamı vardır, burada diğer dillerde değiller ve bu yüzden genellikle bir astardırlar (bazen birden fazla satıra
sarılırlar

14
@Rado: Perl, örneğin, boşlukun xyok sayılmasına neden olan normal ifadeler için değiştiriciye sahiptir . Bu, normal ifadeyi birkaç satıra koymanıza ve yorum eklemenize olanak tanır.
Nathan Fellman

9
Aynı şekilde Python da re.Xaka re.VERBOSE.
Craig McQueen

2
Aynı şekilde xtcl'deki değiştirici. Diğer dillerden farklı olarak PCRE kullanmadığından tcl'nin oldukça standart olduğuna inanıyorum.
slebetman

2
@AndrewC Bu, bu yazının alabileceği en kaba yanlış yorumlardan biri.
Jasper Bekkers

28

Yaygın olarak kabul edilen IDE'lerde en popüler öğrenme aracından yoksun oldukları için: Regex Sihirbazı yoktur. Otomatik Tamamlama bile değil. Her şeyi kendiniz kodlamanız gerekiyor.


3
Sonra yanlış IDE kullanıyorsunuz ... Metin düzenleyicim bile regex ipuçları veriyor.
CurtainDog

1
Bir yanda, Expresso ve The Regex Coach düzenli ifadeler oluşturmak için çok yararlı araçlardır.
Mun

22
Dünyada düzenli bir ifadeyi nasıl otomatik olarak tamamlarsınız?
AmbroseChapel

3
EditPad Pro'da arama kutusunda regexes için sözdizimi vurgulama var, ancak yararlıdan daha sinir bozucu buluyorum ve kapalı tutuyorum. Ama eşsiz parantezlerim olduğunda bana haber vermesini takdir ediyorum; özellikle parantezler takip edilmesi gereken bir ayı olabilir.
Alan Moore

2
@AmbroseChapel - Bu tartışmaya birkaç yıl geç kaldım. Ancak regexhero.net/tester'da bir otomatik tamamlama mekanizması oluşturdum. Yuvarlak (), kare []veya kıvırcık {}parantez içindeki ortak yapılar tarafından başlatıldı . Ayrıca ters eğik çizgiden de çıkar.
Steve Wortham


16

Onların bu kadar tartışmalı olduklarını sanmıyorum.

Ben de kendi sorunuzu cevapladığınızı düşünüyorum, çünkü onları her yerde kullanmanın ne kadar aptalca olduğuna dikkat çekiyorsunuz ( Her şey normal bir dil değildir 2 ) veya bunları kullanmaktan kaçınmaktır. Programcı olarak, düzenli ifadelerin koda ne zaman yardım edeceği veya ona zarar vereceği konusunda akıllıca bir karar vermelisiniz. Böyle bir kararla karşı karşıya kaldığında, akılda tutulması gereken iki önemli şey, sürdürülebilirlik (okunabilirliği ima eder) ve genişletilebilirliktir.

Onlara özellikle karşı olanlar için, tahminimce onları düzgün kullanmayı asla öğrenmediler. Bence iyi bir eğitici ile sadece birkaç saat geçiren çoğu kişi onları anlayacak ve çok hızlı akıcı olacak. İşte nereden başlayacağımla ilgili önerim:

http://docs.python.org/howto/regex

Bu sayfa Python bağlamındaki düzenli ifadelerden bahsediyor olsa da, bilgilerin başka yerlerde çok uygulanabilir olduğunu gördüm. Python'a özgü birkaç şey var, ancak açıkça belirtildiğine ve hatırlanması kolay olduğuna inanıyorum.



@DMan Teşekkürler. Cevabımı yansıtacak şekilde düzenleyeceğim.
allyourcode

11

Düzenli ifadeler, aritmetik işleçlerin sayılara ne olduğunu dizelerdir ve bunları tartışmalı olarak kabul etmem. Kendim gibi oldukça militan bir OO aktivisti bile (dizeler üzerinde diğer nesneleri seçme eğilimi gösteren) bile onları reddetmek için zor olurdu.


7

Sorun şu ki, normal ifadeler potansiyel olarak o kadar güçlüdür ki onlarla birlikte farklı şeyler kullanmanız gerekir.

İyi bir programcı nerede kullanılacağını ve nerede kullanılamayacağını bilmelidir. Tipik örnek, normal olmayan dilleri ayrıştırmaktır (bkz. Bir dilin normal olup olmadığına karar verme ).

İlk başta kendinizi gerçek düzenli ifadelerle (uzantısız) kısıtlarsanız yanlış gidemeyeceğinizi düşünüyorum . Bazı uzantılar hayatınızı biraz daha kolaylaştırabilir, ancak gerçek bir normal ifade olarak ifade edilmesi zor bir şey bulursanız , bu normal ifadenin doğru araç olmadığının bir göstergesi olabilir.


5

Neredeyse goto'ların neden tartışmalı olduğunu soruyor olabilirsiniz.

Temel olarak, çok "bariz" bir güç elde ettiğinizde, insanlar en iyi seçenek olmadığı durumlar için onları kötüye kullanmaya eğilimlidirler. CSV'leri veya XML veya HTML'yi normal ifadelerde ayrıştırmak isteyen kişi sayısı, örneğin beni hayrete düşürüyor. Bu iş için yanlış araç. Ancak bazı kullanıcılar zaten regexes kullanmakta ısrar ediyorlar.

Şahsen, mutlu ortamı bulmaya çalışıyorum - iyi oldukları şey için normal ifadeler kullanın ve optimalden daha az olduklarında onlardan kaçının.

Normal ifadelerin CSV'leri, XML, HTML vb. Ayrıştırmak için hala kullanılabileceğini unutmayın. Ancak genellikle tek bir normal ifadede kullanılamaz.


Elbette bu biçimlerden herhangi birini tek bir regex'te ayrıştırabilirsiniz, bu regexlerin gücüdür bebeğim! Bunu yapmak isteyip istemediğiniz tamamen farklı bir konudur.
Jasper

4

"Tartışmalı" kelimesinin doğru kelime olduğunu sanmıyorum.

Ama insanların "böyle ve böyle bir dize manipülasyonu yapmak için ihtiyacım olan düzenli ifade nedir?" Dediği tonlarca örnek gördüm. bunlar XY problemleridir.

Başka bir deyişle, regex'in ihtiyaç duydukları şey olduğu varsayımından yola çıkmışlardı, ancak bir split (), perl'in tr /// gibi karakterlerin diğeriyle değiştirildiği bir çeviri ile daha iyi olurdu veya sadece bir dizin ().


4

Bu ilginç bir konu.
Birçok normal ifade meraklısı, formülün kısalığı verimlilikle karıştırıyor gibi görünüyor.
Bunun da ötesinde, çok fazla düşünce gerektiren bir regexp, yazarına, onu meşru kılan büyük bir memnuniyet yaratır.

Ancak ... regexps, performans bir sorun olmadığında ve örneğin Perl'de bir metin çıktısıyla hızlı bir şekilde ilgilenmeniz gerektiğinde çok uygundur. Ayrıca, aynı zamanda performans olduğunu bir sorun sadece bir arabası ya da daha az verimli olabilecek bir ev yapımı algoritma kullanarak regexp'in kütüphanesini yenmek için denemek için tercih edebilirsiniz.

Ayrıca, normal ifadelerin haksız yere eleştirilmesinin birkaç nedeni vardır.

  • regexp verimli değil, çünkü en iyiyi oluşturmak belli değil
  • bazı programcılar birçok kez kullanılacak bir normal ifadeyi yalnızca bir kez derlemeyi "unutur" (Java'daki statik bir Desen gibi)
  • bazı programcılar deneme yanılma stratejisine - regexps ile daha da az çalışır!

4

Bence Regex'i Öğrenme ve regex'i popüler olmayan bir şekilde sürdürme, geliştiricilerin çoğu tembel ya da çoğu kendileri için ayrıştırma yapmak için harici kütüphanelere güveniyorlar ... cevap için google'a güveniyorlar ve hatta forumlarda soruyorlar sorunları için tam kod. Ancak bir normal ifadeyi uygulamak veya değiştirmek / korumak söz konusu olduğunda başarısız olurlar.

"Arkadaşların HTML'yi Ayrıştırmak için Regex'i kullanmasına izin verme"

Ama endişelendiğim kadarıyla Regex kullanarak tam HTML ayrıştırıcılar yaptım ve ben kendi regex html dizeleri hem hızlı hem de bellek açısından ayrıştırmada daha iyi olduğunu buluyorum (eğer bir Fikir varsa ne elde etmek için :))


2
Sanırım çoğu geliştiriciyi tembel olarak yazmak çok garip. Sözdiziminin çok şifreli, sezgisel ve gotchas ile dolu olduğunu söyleyebilirim, bu da yüksek bir giriş engeline yol açar. Aynı nedenden ötürü Perl, birçoğu için "kötü" bir üne sahiptir, ancak aynı zamanda çok güçlü bir dildir. Sembolleri bilmeden önce matematiksel ifadeleri okumaya çalışmak gibidir. Bu göz korkutucu ve geliştiriciler bu sözdizimini öğrenmek için fayda sağlayabileceklerini bilmek için zamanlarını yargılamak zorundalar.
Katastic Voyage

Sen edecek HTML düzenli dil olmadığı için HTML sınır durumları özledim.
Amacınız

2

Düzenli ifadeler, ben dahil birçok insan için ciddi bir gizemdir. Harika çalışıyor ama matematik denklemine bakmak gibi. Birinin nihayet http://regexlib.com/ adresinde çeşitli düzenli ifade işlevlerinin birleştirilmiş bir konumunu oluşturduğunu bildirmekten memnuniyet duyuyorum . Şimdi Microsoft, yalnızca harfleri ortadan kaldırmak veya tarihleri ​​filtrelemek gibi sık kullanılan şeylerin çoğunu otomatik olarak yapacak normal bir ifade sınıfı oluşturacaksa.


2
Konuyu kaçırıyorsun. Regexes fikri, onları öğrenmek için biraz zaman ayırmanız ve işiniz bittiğinde, artık sihirli bir "tarih okuma" sınıfına ihtiyacınız yok. Bunun yerine, onlar için çok az çaba gerektirir. Dahası, bir "yyyy / aa / gg" için bir tane yazmak, "aa-gg-yyyy" için bir tane yazmak, hatta "aa-yyyy / gg" için bir tane yazmak kadar az çaba gerektirir. Sık sık gerçekleşmez, ancak bu büyülü bir sınıfın asla yapamayacağı şeyleri nasıl yapabileceğinizin bir örneğidir ").
Jasper

1

Düzenli ifadeleri zaman zaman çok değerli buluyorum. Bazı "bulanık" aramalar yapmam gerektiğinde ve belki de yerine geçer. Veriler ne zaman değişebilir ve belirli bir rastgele olabilir. Ancak, basit bir arama yapmak ve değiştirmek veya bir dize kontrol etmek gerektiğinde, düzenli ifadeler kullanmıyorum. Her ne kadar tanıyan birçok insan tanıyorsam da, her şey için kullanıyorlar. Bu tartışma.

Duvara çakmak istiyorsanız, çekiç kullanmayın. Evet, işe yarayacak, ancak çekiç aldığınız zaman duvara 20 çiviyi koyabilirim.

Düzenli ifadeler, tasarlandıkları şey için kullanılmalı ve daha azı kullanılmamalıdır.


0

Normal ifadelerin önemli bir araç olduğunu düşünmeme rağmen, onlar hakkında en sinir bozucu şey farklı uygulamalar olmasıdır. Sözdizimi, değiştiriciler ve -özellikle- açgözlülükteki küçük farklılıklar, işleri gerçekten kaotik hale getirebilir, deneme yanılma gerektirebilir ve bazen şaşırtıcı hatalar üretebilir.


Normal ifade uygulamaları, “açgözlülük” dediğini düşündüğüm şey olan maksimum eşleşmeye yaklaşımlarında nasıl farklılık gösterir? En soldaki en uzun ile en uzun soldaki anlambilim arasındaki farkı mı kastediyorsunuz ? Fark ettiğim tek fark bu; yani, açgözlülük hevesle yüzleşir ya da tam tersi .
tchrist

0

Bazı durumlarda bunları kullanmanız gerektiğini düşünüyorum. Örneğin bir lexer oluşturmak için.

Benim düşünceme göre, bu normal ifade yazabilen ve yazmayan (ya da neredeyse hiç) olmayan kişilerin bakış açısıdır. Ben kişisel bir şey bu örneğin, bir uyarının giriş geçerli, kullanıcı uyarmak için javascript, ya da sunucu tarafı dilde iyi bir düşünmek olduğunu.


0

Programcılar arasında daha az bilinen bir teknik olduğunu düşünüyorum. Yani, geniş bir kabul görmüyor. Kodunuzu incelemek veya çalışmanızı gözden geçirmek için teknik olmayan bir yöneticiniz varsa, düzenli bir ifade çok kötüdür. Mükemmel bir düzenli ifade yazmak için saatler harcayacaksınız ve modülün bu kadar az kod satırı yazdığını düşünmesi için birkaç not alacaksınız. Ayrıca, başka bir yerde söylendiği gibi, düzenli ifadeleri okumak çok zor bir iştir.


1
Düzenli ifadeleri okumak, yalnızca onları hazırlayan programcı, boşluk, yorumlar, alfasayısal tanımlayıcılar ve belki de gecikmeli yürütme yoluyla gömülü alt yordamları kullanamadığı zaman zor bir iştir. Kısacası, genel programlamaya uygulanabilecek tüm yazılım mühendisliği teknikleri de düzenli ifadelerle takip edilmelidir. Bu ilkeler göz ardı edilirse, yazar profesyonel kod üretmez.
tchrist

Müdürünüzün "Programlamanın gerçek kahramanı negatif kod yazan kişidir" diye bilmediğini düşünüyorum.
Rajeev

Yöneticiniz, işi 3 satırlık kodla (regexps dahil) gerçekleştirdiğiniz için ölecekse, 900 Assembler satırında bunu yapan bazı doofus iş arkadaşlarına övgü ... Yeni bir iş bulmanızı öneririm.
Phil Perry

0

Derleyici tanımı için lex ve yacc'de kullanılan gibi düzenli düzenli ifade sistemleri iyi, çok kullanışlı ve temizdir. Bu sistemlerde, ifade türleri diğerleri açısından tanımlanır. 'Tartışmalı' (çöp) olan perl ve sed kodlarında (vb.) Yaygın olarak bulunan iğrenç, hatalı biçimlendirilmiş okunamayan hat gürültüsü devi tek katmanlı düzenli ifadelerdir.


-4

Normal ifade için en geçerli ve normal kullanım, e-posta adresi biçimi doğrulamasıdır.

Bu iyi bir uygulama.

Düz dosyaları masaj, csv dosyaları oluşturmak, SQL ekleme deyimleri ve bu tür bir şey oluşturmak için TextPad bir kerelik olarak düzenli ifadeler sayısız kez kullandım.

İyi yazılmış düzenli ifadeler çok yavaş olmamalıdır. Genellikle, tonlarca Değiştir çağrısı gibi alternatifler çok daha yavaş seçeneklerdir. Tek geçişte de yapabilir.

Birçok durum tam olarak düzenli ifadeler gerektirir ve başka hiçbir şey gerektirmez.

Özel, yazdırılmayan karakterlerin zararsız karakterlerle değiştirilmesi de iyi bir kullanımdır.

Tabii ki, sürdürülebilirliğin zararına düzenli ifadeleri aşırı kullanan bazı kod tabanları olduğunu hayal edebiliyorum. Bunu hiç görmedim. Aslında yeterince düzenli ifadeler kullanmadığınız için kod yorumcular tarafından eschewed.


10
Deneyimler, normal ifadelerin aslında e-posta adresi biçimi doğrulaması için oldukça zayıf bir araç olduğunu göstermektedir. Normal ifade olarak uygulanan tam kapsamlı bir biçim doğrulayıcı, çok yüzlü bir canavarlıktır, çoğu insanın oluşturmak için 5 dakika sürdüğü "yeterince iyi" doğrulayıcıların çoğu, geçerli, teslim edilebilir büyük adres kategorilerini reddedecektir.
Dave Sherohman

Seni duyuyorum dostum. "Yeterince iyi" hakkında konuşuyordum ve büyük çapaklar teorik olarak büyük olsa da, bu kadar kısa bir ifadede aldığınız kapsama yüzdesini düşünün. Ben de canavarlığı gördüm, ama zarif alternatifin nedir?
Chris Morley

2
Hızın önemli olduğu ve birkaç yanlış pozitif veya yanlış negatifin önemli olmadığı büyük bir dosya dizininde e-posta adresini hızlı bir şekilde bulmak için \ w @ \ w +. \ W + gibi bir şey kullandım. Ancak bir e-posta adresini doğrulamanın en iyi yolu, ona bir e-posta göndermektir.
RossFabricant

Evet e-posta adresi spec kötü bir karmaşa olduğunu stackoverflow.com/questions/611775/…
Nick Van Brunt

@Nick, @Dave: Posta adresi doğrulamasının kötü bir karışıklık olması gerekmez.
tchrist
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.