“Şimdi iki sorunun var” ile ne kastedilmektedir?


200

Orada tarafından popüler bir alıntı Jamie Zawinski :

Bazı insanlar, bir sorunla karşılaştığında, "Biliyorum, düzenli ifadeler kullanacağım" deyin. Şimdi onların iki problemi var.

Bu teklifin nasıl anlaşılması gerekiyor?


46
İkinci sorun ise regex kullanıyor olmaları ve hala ilk problemi çözememeleri, dolayısıyla 2 problemleri.
Ampt

24
@Euphoric - aslında iyi kod olduğunu ama cryptically özlü olmadan - kısa.
Steve314

24
@ IQAndreas: Yarı komik olması gerektiğini düşünüyorum. Yapılan yorum, eğer dikkatli olmazsanız, düzenli ifadeleri kullanmak, işleri daha iyi yapmaktan daha kötü hale getirebileceğidir.
FrustratedWithFormsDesigner

145
Bazı insanlar bir şeyi açıklamaya çalışırken, "Biliyorum, bir Jamie Zawinski alıntı kullanacağım" deyin. Şimdi açıklamak için iki şeyleri var.
saat

Yanıtlar:


220

Bazı programlama teknolojileri genellikle programcılar tarafından iyi anlaşılmamaktadır ( düzenli ifadeler , kayan nokta , Perl , AWK , IoC ... ve diğerleri ).

Bunlar, doğru problemleri çözmek için inanılmaz güçlü araçlar olabilir. Özellikle normal ifadeler normal dilleri eşleştirmek için çok kullanışlıdır. Ve sorunun özü de var: çok az insan düzenli bir dili nasıl tanımlayacağını bilmez (komik sembolleri kullanan bilgisayar bilimleri teorisi / dilbiliminin bir parçasıdır - Chomsky hiyerarşisinde okuyabilirsiniz ).

Bu şeylerle uğraşırken, eğer yanlış kullanırsanız, asıl sorununuzu çözmüş olmanız pek mümkün değildir. Bir kullanarak HTML maç için düzenli ifade (bir çok yaygın bir durum) Eğer anlamına gelecektir olacak sınır durumları özledim. Ve şimdi, hala çözemediğiniz orijinal bir probleminiz var ve çevresinde dolanan başka bir ince böcek de yanlış çözümü kullanarak ortaya çıkıyor.

Bu, düzenli ifadelerin kullanılmaması gerektiği anlamına gelmez, bunun yerine, ne tür sorunları çözebileceklerini ve çözemediklerini ve usluca kullanamadıklarını anlamak için çalışmak gerekir.

Yazılımı korumanın anahtarı, bakım kodu yazmaktır. Düzenli ifadeler kullanmak bu hedefe karşı olabilir. Düzenli ifadelerle çalışırken, özel bir etki alanına özgü dilde bir mini bilgisayar (özellikle belirleyici olmayan sonlu durum otomatları ) yazdınız . 'Merhaba dünyayı' eşdeğerini bu dilde yazmak kolaydır ve ona temel bir güven kazandırır; normal ifadenin içinde bulunduğu programın bir parçası değillerdir).

Şimdi yeni bir probleminiz var; Bunu çözmek için normal ifadenin aracını seçtiniz (uygun olmadığında) ve her ikisini de bulmak daha zor olan iki hataya sahipsiniz, çünkü başka bir soyutlama katmanında saklanmışlar.


8
Perl'in programcılar tarafından iyi anlaşılmayan bir teknolojiler listesine girdiğinden emin değilim;)
crad

21
@crad onun perl hakkında da söylendiğinden daha fazla ... Birçok insan orada popüler olduğunu duymuş. Rand sohbetindeki kayan noktadan hala hoşlanıyorum: "Şimdi 2.00000152 sorununuz var"

56
@crad Bazı insanlar, bir problemle karşılaştıklarında "biliyorum, perl kullanacağım" deyin. Şimdi $ (^ @ #% () ^%) (#) problemi var.
Michael Hampton

4
@ Bir şey varsa, PCRE'nin geleneksel regex'e ek gücü daha cazip bir çözüm sunar ve bakımını zorlaştırır. PCRE'nin eşleştiği sonlu otomatlar, Sonlu Otomatları Perl Uyumlu Düzenli İfadeleri Etkin Bir Şekilde Eşleştirmek için Genişletme bölümünde ve bunun önemsiz bir şeyinde araştırılmıştır . En azından geleneksel regex ile, gerekli kavramlar anlaşılınca başını etrafı çok fazla sıkıntıya sokmadan çözebilir .

6
İyi bir noktaya değindin. Düzenli ifadeler etkili bir şekilde ikinci, önemsiz bir dildir. Orijinal programcı ana dilde ve kullanılan regex'in lezzetinde yetkin olsa bile, bir "ikinci dilde" eklemek, bakıcıların her ikisini de tanıyabilecekleri düşük olasılık anlamına gelir. Regex okunabilirliğinin genellikle "ev sahibi" dilden daha düşük olduğunu söylemeye gerek yok.
JS.

95

Düzenli ifadelerin - özellikle önemsiz ifadelerin - kodlanması, anlaşılması ve sürdürülmesi potansiyel olarak zordur. Sadece [regex], sorgulayan kişinin problemlerinin cevabının bir regex olduğunu ve daha sonra sıkışıp kaldığını varsaydığı etiketli Stack Overflow etiketli soru sayısına bakmak zorundasınız. Birçok durumda sorun farklı bir şekilde çözülebilir (ve belki de gerekir).

Bunun anlamı, eğer bir regex kullanmaya karar verirseniz, şimdi iki probleminiz var:

  1. Çözmek istediğiniz asıl sorun.
  2. Bir regex'in desteği.

Temel olarak, sanırım sorununuzu çözmenin başka bir yolu yoksa, yalnızca bir regex kullanmanız gerektiği anlamına gelir. Başka bir çözüm muhtemelen kodlaması, bakımı ve desteklenmesi daha kolay olacaktır. Daha yavaş veya daha az verimli olabilir, ancak eğer kritik değilse, bakım ve destek kolaylığı en önemli husus olmalıdır.


27
Ve daha da kötüsü: İnsanları, HTML gibi, yapamadıklarını ayrıştırmak için onları kullanmayı denemeye zorlayacak kadar güçlüler. SO ile ilgili çok sayıda soruya bakın "HTML'yi nasıl ayrıştırırım?"
Frank Shearar

6
Bazı durumlar için regex harikadır. Diğer birçok durumda, çok değil. Diğer ucunda korkunç bir umutsuzluk çukuru var. Sorun genellikle, birileri ilk defa öğrendiğinde ve uygulamaları her yerde görmeye başladığında ortaya çıkar. Bir başka ünlü sözler: "Sahip olduğunuz tek alet bir çekiç olduğunda, her şey bir çiviye benziyor."
Todd Williamson,

3
Bu, SO [c #] etiketindeki soru sayısı ile anlaşılması en zor programlama dili anlamına mı geliyor?

2
Dize yöntemlerine yapılan uzun çağrı dizisinden ziyade karmaşık bir düzenli ifade görmeyi tercih ederim. OTOH, karmaşık dilleri ayrıştırmak için kullanılan normal ifadeleri görmekten nefret ediyorum.
kevin cline

5
“Temel olarak, sorununuzu çözmenin başka bir yolu yoksa, yalnızca bir regex kullanmanız gerektiğini düşünüyorum. Başka bir çözümün kodlaması, bakımı ve desteği kolay olacak.” - cidden katılmıyorum .. Regexes mükemmel bir araçtır, sadece onların sınırlarını bilmek zorunda. Regex'lerle birçok görev daha zarif bir şekilde kodlanabilir. (ancak, sadece bir örnek vermek için, HTML'yi ayrıştırmak için kullanmamalısınız)
Karoly Horvath

69

Çoğunlukla bir yanak dili şakasıdır, hakikaten de olsa.

Düzenli ifadelerin mükemmel bir uyum sağladığı bazı görevler vardır. Bir keresinde, 500 satırlık elle yazılmış özyinelemeli ayrıştırıcı kodunu tamamen hata ayıklamak için yaklaşık 10 dakika süren düzenli bir ifadeyle değiştirdim. İnsanlar regex'lerin anlaşılmasının ve hata ayıklanmasının zor olduğunu, ancak uygun şekilde uygulananların büyük bir el tasarımcısı gibi hata ayıklamak kadar zor olmadığını söylüyor. Benim örneğimde, regex olmayan çözümün tüm son vakalarını hata ayıklamak iki hafta sürdü.

Bununla birlikte, Ben Amca'nın ifadesini kullanmak:

Büyük bir verimlilik ile büyük sorumluluk gelir.

Başka bir deyişle, regex'ler, dilinize etkililik katar, ancak programcıya verilen görev için en okunabilir ifade modunu seçme konusunda daha fazla sorumluluk getirir.

Bazı şeyler başlangıçta normal ifadeler için iyi bir iş gibi görünür, ancak değildir. Örneğin, HTML gibi iç içe jetonlu herhangi bir şey. Bazen insanlar daha basit bir yöntem daha açık olduğunda düzenli ifade kullanırlar. Örneğin string.endsWith("ing"), eşdeğer regex'ten daha kolay anlaşılır. Bazen insanlar büyük bir sorunu tek bir regex'e sıkıştırmaya çalışırlar; Bazen insanlar uygun soyutlamalar oluşturamazlar, aynı işi yapmak için iyi adlandırılmış bir işlev oluşturmak yerine tekrar tekrar bir regex tekrarlayın (belki de bir regex ile dahili olarak uygulanır).

Bazı nedenlerden dolayı regex'ler, tek bir sorumluluk ve DRY gibi normal yazılım mühendisliği prensiplerine kör bir nokta oluşturma eğiliminde. Bu yüzden onları seven insanlar bile zaman zaman problemli buluyorlar.


10
Ben Amca da "Her seferinde mükemmel sonuçlar" demedi mi? Belki de bu yüzden insanlar regex'lerle çok mutlu oluyorlar ...
Andrzej Doyle

4
Regex'in deneyimsiz geliştiricileri yukarı çeken HTML ile ilgili sorunu, HTML’nin bağlamsız bir dilbilgisine sahip olmasıdır; karmaşık bir şey için uygun değildir. Bunun için DOM ayrıştırması daha uygundur. İlgili okuma: Chomsky hiyerarşisi .

53

Jeff Atwood bir blog yazısında bu alıntıyı tartışan farklı bir yorum getiriyor: Düzenli İfadeler: Şimdi İki Sorunuz Var ( link için Euphoric sayesinde )

Jamie'nin yayınlarının tam metnini 1997'deki orijinal başlıkta inceleyerek aşağıdakileri bulduk:

Perl'in doğası, neredeyse diğer tüm tekniklerin hariç tutulması için düzenli ifadelerin kullanılmasını teşvik eder; A noktasından B noktasına ulaşmanın en açık ve en açık yolu (en azından daha iyisini bilmeyen insanlar için).

İlk teklif ciddiye alınamayacak kadar glib. Ama buna tamamen katılıyorum. İşte Jamie'nin yapmaya çalıştığı nokta şudur: normal ifadelerin kendi başına kötü olmadığı, ancak normal ifadelerin aşırı kullanılması kötüdür.

Eğer bile yok tamamen normal ifadeler anlamak içine çalıştırmak Altın Çekiç daha kolay ve (ayrıca bkz düzenli kodu ile aynı şeyi yapmak için daha net olurdu zaman düzenli ifadeler, bir sorunu çözmek için çalışıyor, sorunun CodingHorror: Regex kullanımı Regex kötüye vs ).

Alıntı içeriğine bakan ve Atwood'dan daha fazla ayrıntıya giren başka bir blog yazısı daha var: Jeffrey Friedl'in Blogu: Ünlü “Şimdi iki problemin var” alıntı


3
Bu, aklıma en iyi cevap çünkü bağlam ekler. JWZ'ın regex eleştirisi, Perl hakkında bir şeydi.
Evicatos

3
@Evicatos Başka bir blog yazısında aynı 1997 konu üzerinde daha fazla araştırma yapıldı: regex.info/blog/2006-09-15/247
IQAndreas

30

Bu alıntı ile devam eden birkaç şey var.

  1. Alıntı önceki bir şaka bir yeniden ifade geçerli:

    Bir problemle karşılaştığında, bazı insanlar "Hadi AWK kullanalım" diyor. Şimdi onların iki problemi var. - D. Tilbrook

    Bu bir şaka ve gerçek bir kazı, ama aynı zamanda regex'i diğer kötü çözümlerle ilişkilendirerek kötü bir çözüm olarak vurgulamanın bir yolu. Çok ciddi bir an.

  2. Bana göre - aklınızdan çıkarmayın, bu alıntı bilerek açıklamaya açık - anlam açıktır. Basitçe, düzenli bir ifade kullanma fikrini duyurmak problemi çözmedi. Ek olarak, kullandığınız dilden farklı olan kurallara ek bir dil ekleyerek, kodun bilişsel karmaşıklığını arttırdınız.

  3. Şaka kadar komik olsa da, regex olmayan bir çözümün karmaşıklığını regex çözümünün karmaşıklığıyla + regex içeren ek karmaşıklıkla karşılaştırmanız gerekir. Ek regex ekleme maliyetine rağmen, regex ile ilgili bir sorunu çözmek faydalı olabilir.


21

RegularExpressionsarenoworsetoreadormaintainthananyotherunformattedcontent; indeedaregexisprobablyeasiertoreadthanthispieceoftexthere-butunfortunatelytheyhaveabadreputationbecausesomeimplementationsdon'tallowformattingandpeopleingeneraldon'tknowthatyoucandoit.

(Düzenli İfadeler, biçimlendirilmemiş diğer herhangi bir içerikten okumak veya bakım yapmaktan daha kötü değildir; aslında, bir regex'in bu metinden daha kolay okunması daha kolaydır - ancak ne yazık ki, kötü bir üne sahiptir, çünkü bazı uygulamalar genel olarak biçimlendirmelere ve insanlara izin vermez Yapabileceğini bilmiyorum.)


İşte önemsiz bir örnek:

^(?:[^,]*+,){21}[^,]*+$


Zaten okumak ya da sürdürmek o kadar zor değil, ama böyle göründüğünde daha da kolay:

(?x)    # enables comments, so this whole block can be used in a regex.
^       # start of string

(?:     # start non-capturing group
  [^,]*+  # as many non-commas as possible, but none required
  ,       # a comma
)       # end non-capturing group
{21}    # 21 of previous entity (i.e. the group)

[^,]*+  # as many non-commas as possible, but none required

$       # end of string

Bu $, başa çıkmış bir örnek (yorum yapmaktan başka bir şey i++değil) ama açıkça okumak, anlamak ve sürdürmekle ilgili hiçbir sorun olmamalı.


Düzenli ifadelerin ne zaman uygun olduğu ve ne zaman kötü bir fikir olduğu konusunda net olduğunuz sürece, onlarla ilgili yanlış bir şey yoktur ve çoğu zaman JWZ teklifi gerçekten geçerli olmaz.


1
Tabii, ama regex'lerin esası hakkında tartışmalar aramıyorum ve bu tartışmanın böyle yürüdüğünü görmek istemiyorum. Sadece ne yaptığını anlamaya çalışıyorum.
Paul Biggar

1
Daha sonra livibeter'in yorumundaki link size bilmeniz gerekenleri söyler. Bu cevap, regex'lerin belirsiz olmaları gerekmediğine işaret ediyor ve bu yüzden alıntı saçma.
Peter Boughton

8
Kullanmanın amacı nedir *+? Bunun (işlevsel olarak) adil olandan farkı *nedir?
Timwi

1
Söyledikleriniz doğru olsa da, bu belirli soruyu cevaplamıyor. Cevabınız "Bence alıntı genellikle doğru değil" dür. Soru, doğru olup olmadığı değil, teklifin ne anlama geldiği ile ilgili değil.
Bryan Oakley

2
*+Bu durumda tam anlamıyla bir anlam ifade etmiyor ; her şey sabitlenir ve 22'ye kadar sayılabilecek bir otomat tarafından tek bir geçişte eşleştirilebilir. Bu virgül olmayan kümelerdeki doğru değiştirici sadece eskidir *. (Dahası, burada açgözlü ve açgözlü olmayan eşleştirme algoritmaları arasında da bir fark olmamalıdır. Bu son derece basit bir durumdur.)
Donal Fellows

14

ChrisF’in cevabına ek olarak - normal ifadelerin “kodlanması, anlaşılması ve sürdürülmesi zor”, daha da kötüsü: insanları HTML gibi, yapamadıkları şeyleri ayrıştırmak için kullanmaya kandırmaya yetecek kadar güçlüler. SO ile ilgili çok sayıda soruya bakın "HTML'yi nasıl ayrıştırırım?" Örneğin, tüm SO'daki en destansı cevap !


14

Düzenli ifadeler çok güçlüdür, ancak bir küçük ve büyük bir sorunu vardır; yazmak zor ve okumak imkansız.

En iyi durumda, normal ifadenin kullanılması sorunu çözer, bu nedenle yalnızca karmaşık kodun bakım sorununu yaşarsınız. Düzenli ifadeyi tam anlamıyla anlamazsanız, hem orijinal hem de çalışmayan okunamayan kodla ilgili bir sorun yaşarsınız.

Bazen normal ifadelere salt okunur kod denir. Düzeltme gerektiren düzenli bir ifadeyle karşılaşıldığında, sıfırdan başlamak ifadeyi anlamaya çalışmaktan daha hızlıdır.


1
Asıl sorun, regexps'in örneğin bir ayrıştırıcı uygulayamamasıdır, çünkü şu anda ne kadar iç içe olduklarını hesaplayamazlar.

4
@ Thorbjørn Ravn Andersen: Bu bir problemden çok bir sınırlama. Yalnızca bunun için normal ifadeler kullanmaya çalışırsanız sorun olur ve ardından normal ifadelerle ilgili bir sorun olmazsa, yöntem seçiminizle ilgili bir sorun olur.
Guffa

1
RE'i sadece lexer için gayet iyi kullanabilirsiniz (pek çok dil için) ancak token akışını ayrıştırma ağacına (yani ayrıştırma ) montajları resmi olarak bunların ötesindedir.
Donal Fellows

10

Sorun şu ki regex karmaşık bir canavardır ve sadece regex'i mükemmel kullanırsanız sorununuzu çözersiniz. Aksi takdirde, 2 sorunla karşılaşırsınız: asıl sorununuz ve regex.

Yüz satır kod işini yapabileceğini iddia ediyorsunuz, ancak 100 satır açık, özlü kodun bir regex satırından daha iyi olduğu iddiasını da yapabilirsiniz.

Bunun bir kanıtına ihtiyacınız varsa: Bu SO Classic'i kontrol edebilir veya sadece SO Regex Tag'ı kullanarak taraklayabilirsiniz.


8
İlk cümlenizdeki iddiaların hiçbiri gerçek değil. Regex, özellikle karmaşık değildir ve başka hiçbir araç gibi, onunla sorunları çözmek için mükemmel bir şekilde bilmeniz gerekmez. Bu sadece FUD. İkinci paragrafınız oldukça saçma: tabii ki tartışmayı yapabilirsiniz. Ama bu iyi değil.
Konrad Rudolph

1
@KonradRudolph sayısız regex nesil ve doğrulama araçları vardır aslında o regex göstermek için gider düşünüyorum olduğu karmaşık bir mekanizmadır. İnsan tarafından okunamaz (tasarım yoluyla) ve regex kullanan bir kod parçasını değiştiren veya yazan biri için akışta tam bir değişikliğe neden olabilir. İkinci bölüme gelince, P.SE hakkındaki engin bilgi gruplandırmasının ima ettiği ve “Hata ayıklama kodu yazmaktan iki kat daha zor,” diyerek açıklığa kavuşturduğunu düşünüyorum. tanımı gereği, onu ayıklamak için yeterince akıllı değildir "
Ampt

2
Bu uygun bir tartışma değil. Evet, regex'in karmaşık olduğundan emin olun. Fakat diğer programlama dilleri de öyle. Regex diğer birçok dilden çok daha az karmaşıktır ve regex için var olan araçlar, diğer diller için geliştirme araçları tarafından cücedir (FWIW, regex ile yoğun çalışıyorum ve bu tür araçları hiç kullanmamıştım…). Bu, karmaşık regex'in bile eşdeğer regex olmayan ayrıştırma kodundan daha basit olduğu gerçeğidir.
Konrad Rudolph

@KonradRudolph O zaman basit kelimenin tanımı konusunda temel bir anlaşmazlığımız olduğunu düşünüyorum. Size regex'in daha verimli ve hatta daha güçlü olabileceğini söyleyeceğim ama regex'i düşündüğünüzde basit olan birinin aklına gelen kelime olduğunu sanmıyorum.
Ampt

Belki yaptığımız ama benim tanımı eyleme: Ben, bakımı kolay, anlaşılması kolay anlamına basit almak, gizli böcek vb sayısının düşük Tabii karmaşık bir regex ilk bakışta olacak değil çok anlaşılır görünüyor. Fakat aynı şey regex olmayan eşdeğer bir kod parçası için de geçerlidir . Regex'in basit olduğunu hiç söylemedim. Daha basit olduklarını söylüyorum - karşılaştırıyorum. Bu önemli.
Konrad Rudolph

7

Anlamı iki bölümden oluşur:

  • İlk önce asıl sorunu çözmediniz.
    Bu muhtemelen, düzenli ifadelerin sık görülen sorunlara eksik çözümler sunduğunu gösterir.
  • İkincisi, şimdi seçtiğiniz çözümle ilgili ek zorluklar eklediniz.
    Düzenli ifadeler söz konusu olduğunda, ek zorluk muhtemelen karmaşıklık, bakım kolaylığı veya normal ifadelerin çözmesi gerekmeyen bir soruna uyması ile ilgili ek zorluk anlamına gelir.

7

2014'te istediğin gibi, bugünün bağlamına kıyasla 1997 bağlamı ideolojilerini programlama dillerine odaklamak ilginç olurdu. Bu tartışmaya buraya girmeyeceğim ancak Perl ve Perl hakkındaki görüşler büyük ölçüde değişti.

Bununla birlikte, 2013 bağlamında kalmak için ( bir coulé sous les ponts depuis) ​​de, Jamie Zawinski'nin doğrudan bir alıntı olan ünlü bir XKCD çizgi romanını kullanarak alıntılarda canlandırma üzerine odaklanmayı öneririm :

XKCD'den regex'ler, Perl ve sorunlar hakkında bir çizgi roman

Öncelikle ben Zawinski alıntı bir referans, çünkü bu komik anlamak için sorunları vardı ve bir Jay-Z şarkı sözleri bir alıntı ve GNU bir referans program --help -zbayrağı 2 bana bunu anlamak için çok fazla kültürünü oldu, bu yüzden.

Eğlenceli olduğunu biliyordum, hissediyordum ama nedenini bilmiyordum. İnsanlar genellikle Perl ve regex'ler hakkında şakalar yapıyorlar, özellikle de en akıllı programlama dili olmadığı için, neden eğlenceli olması gerektiğini bilmiyorlar ... Belki de Perl satıcıları saçma şeyler yapıyor .

Dolayısıyla ilk alıntı, acı veren araçların programlanmasından kaynaklanan gerçek hayat sorunlarına (acı?) Dayalı alaycı bir şaka gibi görünüyor. Tıpkı bir çekiçin masonlara zarar verebilmesi gibi, geliştiricinin zarar verebilecekse (beyin, duygular) seçeceği araçlarla programlama. Bazen, hangi aracın en iyisi olduğu konusunda büyük tartışmalar olur, ancak neredeyse değersizdir, çünkü bu sizin zevkinize ya da programlama ekibinizin zevkine , kültürel ya da ekonomik nedenlerine göre bir problemdir . Bu konuda bir başka mükemmel XKCD komik:

XKCD'den programlama araçları tartışmalarıyla ilgili bir çizgi roman

İnsanların regex'ler hakkında acı duyduklarını anlayabiliyorum ve regex'lerin ne için tasarlandıkları için başka bir aracın daha uygun olduğuna inanıyorlar. @ Karl-bielefeldt sorunuzu büyük bir verimlilikle yanıtladığından büyük sorumluluk alır ve regex'ler özellikle bundan endişe duyuyor. Eğer bir geliştirici, regex'lerle nasıl ilgilendiğini umursamıyorsa, sonunda şifreyi koruyacak insanlar için bir acı olacaktır.

Damian Conway'ın Perl En İyi Uygulamaları (2005) kitabından tipik bir örnek gösteren bir alıntı ile alıntıların yeniden canlandırılması hakkındaki bu cevabı bitireceğim .

Bunun gibi bir kalıp yazdığını şöyle açıklıyor :

m{'[^\\']*(?:\\.[^\\']*)*'}

... böyle bir program yazmaktan daha fazla kabul edilebilir değildir :

sub'x{local$_=pop;sub'_{$_>=$_[0
]?$_[1]:$"}_(1,'*')._(5,'-')._(4
,'*').$/._(6,'|').($_>9?'X':$_>8
?'/':$")._(8,'|').$/._(2,'*')._(
7,'-')._(3,'*').$/}print$/x($=).
x(10)x(++$x/10).x($x%10)while<>;

Ama yeniden yazılabilir , hala güzel değil, ama en azından şu anda hayatta kalabilir.

# Match a single-quoted string efficiently...
m{ '            # an opening single quote
    [^\\']*     # any non-special chars (i.e., not backslash or single quote)
    (?:         # then all of...`
    \\ .        # any explicitly backslashed char
    [^\\']*     #    followed by any non-special chars
    )*          # ...repeated zero or more times
    '           # a closing single quote
}x

Bu tür bir dikdörtgen biçimli kod , açık, sürdürülebilir ve okunabilir bir şekilde biçimlendirilebilen regex'lerin değil, ikinci problemdir.


2
/* Multiply the first 10 values in an array by 2. */ for (int i = 0 /* the loop counter */; i < 10 /* continue while it is less than 10 */; ++i /* and increment it by 1 in each iteration */) { array[i] *= 2; /* double the i-th element in the array */ }
5gon12eder

6

Bilgisayar bilimlerinden öğrenmeniz gereken bir şey varsa, bu Chomsky hiyerarşisidir . Düzenli ifadelerle ilgili tüm sorunların bağlamsız gramer ayrıştırma girişimlerinden kaynaklandığını söyleyebilirim. CFG'de yuva düzeylerine bir sınır getirebilir (veya bir sınır getirebileceğinizi düşünebilirsiniz), bu uzun ve karmaşık düzenli ifadeleri alırsınız.


1
Evet! Sürekli olarak CS arka planının bir kısmı olmadan düzenli ifadeler öğrenen insanlar, bir regex'in matematiksel olarak yapamayacağı bazı şeyler olduğunu her zaman anlamazlar .
benzado

5

Düzenli ifadeler, tokenizasyon için tam ölçekli ayrıştırmaya göre daha uygundur.

Ancak, programcıların ayrıştırması gereken şaşırtıcı derecede büyük şeyler kümesi düzenli bir dille ayrıştırılabilir (veya daha da kötüsü, normal bir dille neredeyse ayrıştırılabilir ve sadece biraz daha fazla kod yazarsanız ...).

Eğer biri "aha, metni parçalara ayırmam gerekiyor, normal bir ifade kullanacağım" diyene alışkın olursa, aşağıdan aşağıya bir otomat, CFG çözümleyici veya daha da güçlü gramerler. Bu genellikle gözyaşlarıyla biter.

Bu nedenle, teklifin çok fazla çarpıtma olmadığını düşünüyorum, onların kullanımları var (ve çok kullanılmışlar, gerçekten çok faydalılar), ancak regexps'lere aşırı güveniyorlar (ya da özellikle eleştirel olmayan tercihleri) .


3

jwz bu alıntı ile sadece rocker kapalı. Düzenli ifadeler, herhangi bir dil özelliğinden farklı değildir - vidalanması kolay, kullanımı zor, zaman zaman güçlü, zaman zaman uygunsuz, sık sık iyi belgelenmiş, genellikle yararlı.

aynı şey, kayan nokta aritmetiği, kapanışlar, nesne yönelimi, asenkron I / O ya da adlandırabileceğiniz herhangi bir şey için de söylenebilir. Ne yaptığınızı bilmiyorsanız, programlama dilleri sizi üzebilir.

Eğer regexlerin okunmasının zor olduğunu düşünüyorsanız, söz konusu kalıbı tüketmek için eşdeğer çözümleyici uygulamasını okumayı deneyin. sık sık regexes kazanır çünkü tam ayrıştırıcılardan daha küçüktürler ve çoğu dilde de daha hızlıdırlar.

Kendini tanıtıcı bir blog yazıcısının nitelenmemiş ifadeler yaptığı için normal ifadeleri (veya başka bir dil özelliğini) kullanmaktan kaçının. kendiniz için bir şeyler deneyin ve sizin için neyin işe yaradığını görün.


1
FWIW, kayan nokta aritmetiği RE'lerden daha zorludur, ancak daha basit görünür. Dikkat! (En azından aldatıcı RE'ler tehlikeli görünmek eğilimindedir.)
Donal Fellows

3

Buna en sevdiğim, derinlemesine cevabım, dahili bir Google kod yorumundan çoğaltılan bir blog yazısında ünlü Rob Pike tarafından verildi: http://commandcenter.blogspot.ch/2011/08/regular-expressions-in-lexing- and.html

Özet, onların kötü olmadıkları değil , fakat özellikle bazı şeyleri karıştırmak ve ayrıştırmak söz konusu olduğunda mutlaka uygun olmadıkları için görevler için sıkça kullanılıyorlar.

Düzenli ifadeler yazmak zordur, iyi yazmak zordur ve diğer teknolojilere göre daha pahalı olabilir ... Diğer taraftan, Lexers, doğru yazması oldukça kolaydır (kompakt olmasa da) ve test etmesi çok kolaydır. Alfanümerik tanımlayıcıları bulmayı düşünün. Regexp ("[a-ZA-Z _] [a-ZA-Z_0-9] *" gibi bir şey) yazmak çok zor değil, ama basit bir döngü olarak yazmak gerçekten zor değil. Bununla birlikte, döngünün performansı çok daha yüksek olacaktır ve kapakların altında daha az kod bulunacaktır. Düzenli bir ifade kütüphanesi büyük bir şeydir. Birini tanımlayıcıları ayrıştırmak için kullanmak, depoya süt almak için bir Ferrari kullanmak gibidir.

Bundan daha fazlasını, düzenli ifadelerin örneğin metin editörlerinde tek kullanımlık desen eşleştirmesinde yararlı olduğunu, ancak derlenmiş kodda nadiren kullanılması gerektiğini savunarak çok daha fazla olduğunu söylüyor. Okunmaya değer.


0

Bu Alan Perlis'in 34 numaralı epigramı ile ilgilidir:

Dize keskin bir veri yapısıdır ve geçtiği her yerde işlemin çoğaltılması söz konusudur. Bilgi gizlemek için mükemmel bir araçtır.

Bu nedenle, karakter dizginizi veri yapınız olarak seçtiyseniz (ve doğal olarak, onu işlemek için kullanılan algoritmalar olarak regex tabanlı kod), çalışıyor olsa bile bir sorunla karşılaşırsınız: uygun olmayan verilerin gösterimi için kötü tasarım uzatmak ve verimsiz.

Ancak, çoğu zaman işe yaramıyor: orijinal problem çözülmedi ve bu durumda iki probleminiz var.


0

Regex'ler hızlı ve kirli metin ayrıştırma için yaygın olarak kullanılır. Yalnızca düz bir dize eşleşmesinden biraz daha karmaşık olan desenleri ifade etmek için harika bir araçtır.

Ancak regex'ler karmaşıklaştıkça hizmet sorunları başa çıkıyor.

  1. Düzenli ifadelerin sözdizimi basit eşleştirme için optimize edilmiştir, çoğu karakter kendi kendine eşleşir. Bu, basit kalıplar için harikadır, ancak bir kez birkaç iç içe geçme seviyesine sahip olursanız, iyi yapılandırılmış koddan çok, çizgi gürültüsüne benzeyen bir şeyle karşılaşırsınız. Sanırım kodun yapısını göstermek için girintili ve yorumlu birleştirilmiş dizeler dizisi olarak bir regex yazabilirsiniz, ancak bunun gerçekleşmesi nadir görülür.
  2. Yalnızca belirli metin eşleme türleri regex'lere uygundur. Genellikle, bir tür biçimlendirme dili çalışması için hızlı ve kirli bir regex tabanlı ayrıştırıcı edindiğinizi görürsünüz, ancak daha sonra daha fazla köşe kasasını ele almaya çalışırsınız ve regex'lerin gittikçe daha karmaşık ve daha az ve daha az okunabilir hale geldiğini görürsünüz.
  3. Bir regex'in zaman karmaşıklığı obvoius olmayabilir. Eşleştiğinde harika çalışan, eşleşmeyen bazı durumlarda O (2 ^ n) karmaşıklığı olan bir desenle sonuçlanmak o kadar zor değildir .

Bu nedenle, bir metin işleme sorunuyla başlamak, ona düzenli ifadeler uygulamak ve iki sorunla sonuçlanmak çok kolaydır, çözmeye çalıştığınız ve çözmeye çalıştığınız normal ifadelerle uğraşmakta olduğunuz asıl sorun (ancak doğru şekilde çözülmez) asıl sorun.

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.