Düzenli ifade sözdizimi tasarımının zayıf okunabilirliğinin özel bir nedeni var mı?


160

Programcıların hepsi, kodun okunabilirliğinin, çalışanların kısa sözdizimi olan tek gömleklerden çok daha önemli olduğu konusunda hemfikir gibi görünmesine karşın, üst düzey bir geliştiricinin herhangi bir doğruluk derecesi ile yorum yapmasını gerektirir - ancak bu tam olarak normal ifadelerin tasarlanma şekli gibi görünüyor. Bunun bir nedeni var mıydı?

Hepimiz selfDocumentingMethodName()bunun çok daha iyi olduğu konusunda hemfikiriz e(). Bu neden düzenli ifadeler için geçerli olmamalıdır?

Bana öyle geliyor ki, yapısal bir organizasyonu olmayan tek satırlık bir mantık sözdizimi tasarlamak yerine:

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})(0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

Ve bu bir URL'nin kesin olarak ayrıştırılması bile değildir!

Bunun yerine, basit bir örnek için bazı boru hattı yapılarını organize ve okunabilir hale getirebiliriz:

string.regex
   .isRange('A-Z' || 'a-z')
   .followedBy('/r');

Düzenli bir ifadenin son derece kısa sözdiziminin mümkün olan en kısa işlem ve mantık sözdizimi dışında ne avantajı vardır? Sonuçta, düzenli ifade sözdizimi tasarımının zayıf okunabilirliğinin özel bir teknik nedeni var mı?


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
maple_shaft

1
RegexToolbox adlı bir kütüphane ile tam olarak bu okunabilirlik problemiyle uğraşmaya çalıştım. Şimdiye kadar C #, Java ve JavaScript'e taşınıyor - bkz. Github.com/markwhitaker/RegexToolbox.CSharp .
Mark Whitaker,

bu sorunu çözmek için birçok girişimde bulunuldu, ancak kültürün değiştirilmesi zor. burada sözlü ifadeler hakkındaki cevabımı gör . İnsanlar mevcut olan en düşük yaygın araca ulaşır.
Parivar Saraff,

Yanıtlar:


178

Düzenli ifadelerin olduğu kadar özlü olarak tasarlanmasının büyük bir nedeni vardır: kodlanacak bir dil olarak değil, bir kod editörüne komut olarak kullanılmak üzere tasarlanmıştır. Daha doğrusu, ednormal ifadeleri kullanan ilk programlardan biriydi. ve oradan düzenli ifadeler dünya hakimiyeti için fethi başladı. Örneğin, edkomut g/<regular expression>/pkısa süre sonra grephalen kullanılmakta olan ve ayrı bir programa ilham verdi . Çünkü onların gücü, onlar sonradan standardize ve benzeri çeşitli araçlar kullanılmaktadır sedvevim

Ama önemsiz şeyler için yeterli. Öyleyse neden bu kökene kısa bir dilbilgisi tercih ediyor? Çünkü bir kez daha okumak için bir editör komutu yazmazsınız. Nasıl bir araya getireceğinizi hatırlamanız ve yapmak istediğiniz şeyleri onunla yapabilmeniz yeterlidir. Ancak, yazmanız gereken her karakter dosyanızı düzenlerken ilerlemenizi yavaşlatır. Düzenli ifade sözdizimi, nispeten karmaşık aramaları bir fırlatma biçiminde yazmak için tasarlandı ve bu tam olarak, bir programı bir girdiyi ayrıştırmak için onları kod olarak kullanan baş ağrıları veren şeydir.


5
regex ayrıştırma amaçlı değildir. Aksi takdirde, stackoverflow.com/questions/1732348/… . ve baş ağrısı.
njzk2

19
@ njzk2 Bu cevap aslında yanlıştır. Bir HTML belgesi normal bir dil değil , sorunun ne dediği gibi bir HTML açık etiketidir .
Rastgele832

11
Bu, orijinal regex'in neden bu kadar şifreli olduğunu açıklayan iyi bir cevaptır, fakat neden şu anda artan okunabilirlik ile alternatif bir standart olmadığını açıklamamaktadır.
Doc Brown

13
Yani grepyanlış anlaşılmış bir "kapma" olduğunu düşünenler için , aslında g/ re(düzenli ifade için) / p?
Hagen von Eitzen 30:15

6
@DannyPflughoeft Hayır, değil. Açık etiket sadece <aaa bbb="ccc" ddd='eee'>, içine yerleştirilmiş etiket yoktur. Yapabilirsiniz değil ne yuva yuva etiketleri, elemanları soru edildi (alt öğeler, yakın etiketi dahil açık etiket, içeriği) değil ayrıştırma hakkında sorular soruyorlardı. HTML etiketleri normal bir dildir - dengeleme / yuvalama etiketlerin üzerinde bir düzeyde gerçekleşir.
Random832 30:15

62

Alıntı yaptığınız düzenli ifade korkunç bir karmaşa ve kimsenin okunabilir olduğunu kabul etmiyor. Aynı zamanda, bu çirkinliğin çoğu çözülmekte olan sorunun doğasında var: Birkaç iç içe geçme katmanı var ve URL dilbilgisi göreceli olarak karmaşık. Ancak, bu regex'in ne tanımladığını açıklamanın daha iyi yolları olduğu kesinlikle doğrudur. Öyleyse neden kullanılmıyorlar?

Büyük bir neden atalet ve her yerdedir. İlk etapta nasıl bu kadar popüler olduklarını açıklamıyor, ama şimdi onlar, düzenli ifadeleri bilen herkes bu becerileri (lehçeler arasındaki çok az farkla) yüzlerce farklı dilde ve ek bir bin yazılım aracıyla kullanabiliyor ( örneğin, metin editörleri ve komut satırı araçları). Bu arada, sonuncusu, programcı olmayanlar tarafından yoğun olarak kullanıldığı için, program yazmaya değecek herhangi bir çözümü kullanmaz ve kullanamazdı .

Buna rağmen, düzenli ifadeler genellikle fazla kullanılır, yani başka bir araç daha iyi olacağı zaman bile uygulanır. Regex sözdiziminin korkunç olduğunu sanmıyorum . Ancak, kısa ve basit kalıplarda açıkça çok daha iyidir: C benzeri dillerde tanımlayıcıların arketipsel örneği, [a-zA-Z_][a-zA-Z0-9_]*mutlak minimum regex bilgisi ile okunabilir ve bu çubuk bir kez karşılandığında hem bariz hem de güzel bir şekilde özlüdür. Daha az karakter istemek doğal olarak fena değil, tam tersi. Özlü olmak, anlaşılabilir olmanız koşuluyla erdemdir.

Bu sözdiziminin aşağıdaki gibi basit kalıplarda üstün kalmasının en az iki nedeni vardır: Çoğu karakter için kaçmayı gerektirmez, bu nedenle nispeten doğal olarak okunur ve çeşitli basit ayrıştırma birleştiricilerini ifade etmek için mevcut tüm noktalama işaretlerini kullanır. Belki de en önemlisi, sıralama için hiçbir şey gerektirmez . Önce sen, sonra peşinden gelen şeyi sen yaz. SİZİN ile kontrast followedByaşağıdaki kalıptır, özellikle değil bir hazır ama daha karmaşık bir ifade.

Peki neden daha karmaşık durumlarda yetersiz kalıyorlar? Üç ana problem görebiliyorum:

  1. Soyutlama yeteneği yok. Regex'lerle aynı teorik bilgisayar bilimi alanından kaynaklanan biçimsel gramerler, bir dizi üretime sahiptir, böylece desenin orta bölümlerine isimler verebilirler:

    # This is not equivalent to the regex in the question
    # It's just a mock-up of what a grammar could look like
    url      ::= protocol? '/'? '/'? '/'? (domain_part '.')+ tld
    protocol ::= letter+ ':'
    ...
    
  2. Yukarıda gördüğümüz gibi, özel bir öneme sahip olmayan boşluk, gözler üzerinde daha kolay olan biçimlendirmeye izin vermek için kullanışlıdır. Yorumlar ile aynı şey. Düzenli ifadeler bunu yapamaz, çünkü bir boşluk tam anlamıyla hazırdır ' '. Ancak şunu unutmayın: Bazı uygulamalar, boşlukların yok sayıldığı ve yorumların yapılabildiği bir "ayrıntılı" moda izin verir.

  3. Ortak kalıpları ve birleştiricileri tanımlayan bir meta-dil yoktur. Örneğin, biri yazabilir digitkez kural ve bir bağlam serbest dilbilgisi kullanmaya devam, ama bir bir "işlev" öylesine bir üretim verildiği konuşmaya tanımlayamazsınız pörneğin oluşturmak ve bununla ekstra bir şey yapar, yeni bir üretim yaratır virgülle ayrılmış durumların bir listesi p.

Önerdiğiniz yaklaşım kesinlikle bu problemleri çözüyor. Sadece onları çok iyi çözmez, çünkü gereğinden fazla özlü bir şekilde işlemektedir. İlk iki problem göreceli olarak basit ve kısa süreli etki alanına özgü bir dilde kalırken çözülebilir. Üçüncüsü, iyi bir ... programatik bir çözüm elbette genel amaçlı bir programlama dili gerektirir, ancak deneyimlerime göre üçüncüsü bu sorunların en küçüğüdür. Birkaç model, programcının yeni birleştiricileri tanımlama yeteneği için can attığı aynı karmaşık görevin yeteri kadar oluşumuna sahiptir. Ve bu gerekli olduğunda, dil, yine de düzenli ifadelerle ayrıştırılamayacak ve ayrıştırılmayacak kadar karmaşıktır.

Bu davalar için çözümler var. Sadece farklı bir işlem kümesi, genellikle farklı bir sözdizimi ve hemen hemen her zaman normal ifadelerden daha fazla ayrıştırma gücüyle (yani bağlam içermeyen dillerle veya bazı boyutlarla ilgilenirler) Bunların alt kümesi). Daha sonra yukarıda açıklanan “daha ​​iyi bir DSL kullanın” yaklaşımıyla çalışan ayrıştırma jeneratörleri var. Ve her zaman ayrıştırma işleminin bir kısmını el ile uygun kodda yazma seçeneği vardır. Basit alt görevler için normal ifadeler kullanarak ve regex'leri kodlayan karmaşık şeyleri bile yaparak karıştırıp eşleştirebilirsiniz.

Düzenli ifadelerin bu kadar popüler hale geldiğini açıklamak için ilk yıllardaki hesaplama hakkında yeterince bilgim yok. Ama kalmak için buradalar. Sadece bunları akıllıca kullanmak zorunda ve değil o bilgedir zaman bunları kullanın.


9
I don't know enough about the early years of computing to explain how regular expressions came to be so popular.Yine de bir tahminde bulunabiliriz: Temel bir düzenli ifade motorunun uygulanması çok kolaydır, bağlamsız bir ayrıştırıcıdan daha kolaydır.
biziclop

15
@biziclop Bu değişkeni fazla abartmam. Görünüşe göre "bir başka derleyici derleyici" olarak adlandırılabilecek kadar selefine sahip olan Yacc, 70'li yılların başında yaratılmış ve daha önce Unix'e bir sürüm eklenmiştir grep(Sürüm 3 - Sürüm 4).

Sadece Wikipedia'da bulduğum şeye devam edebilirim (bu yüzden% 100 inanmamıştım) ama buna göre, yacc1975 yılında, LALR ayrıştırıcılarının (pratik olarak kullanılabilir ilk sınıfları arasında yer alan ilk sınıf arasında) bütün fikri oluşturuldu. tür) 1973 yılında ortaya çıkmıştır. Oysa JIT'nin ifadelerini (!) 1968'de yayınladığı ilk regexp motor uygulaması. 1968'de yayınlandı. Fakat haklısın, bunu ne salladığını söylemek zor, aslında regex'lerin ne zaman başladığını söylemek zor. "kapalı. Ancak, bir kez metin editörleri kullanan geliştiricilerin kullandıklarından, kendi yazılımlarında da kullanmak istediklerinden şüpheleniyorum.
biziclop

1
@ jpmc26 kitabını açar, JavaScript Regex Bölümünün İyi Parçaları .
Viziionary

2
with very few differences between dialects"Çok az" olduğunu söyleyemem. Önceden tanımlanmış herhangi bir karakter sınıfının farklı lehçeler arasında çeşitli tanımları vardır. Ayrıca her lehçeye özgü ayrıştırma tuhaflıkları da var.
nhahtdh

39

Tarihi bakış açısı

Wikipedia makalesi , düzenli ifadelerin kökenleri hakkında oldukça ayrıntılıdır (Kleene, 1956). Orijinal sözdizimi sadece nispeten basitti *, +, ?, |ve gruplama (...). Özlü ( ve okunabilir, ikisi mutlaka karşı çıkmaz), çünkü biçimsel diller özlü matematiksel notasyonlarla ifade edilme eğilimindedir.

Daha sonra, sözdizimi ve yetenekler editörlerle birlikte gelişti ve tasarımdan etkilenmeye çalışan Perl ile büyüdü ( "ortak yapılar kısa olmalı" ). Bu, sözdizimini çok karmaşıklaştırdı, ancak insanların artık normal ifadelere alıştıklarını ve (eğer okumazsa) yazmada iyi olduklarını unutmayın. Bazen yalnızca yazma olmaları, çok uzun olduklarında genellikle doğru araç olmadıklarını göstermektedir. Normal ifadeler kötüye kullanıldığında okunamaz olma eğilimindedir.

Dize tabanlı normal ifadelerin ötesinde

Alternatif sözdizimleri hakkında konuşalım, şu an var olan şeye bir bakalım ( cl-ppcre , Common Lisp ). Uzun düzenli ifadeniz aşağıdaki gibi ayrıştırılabilir ppcre:parse-string:

(let ((*print-case* :downcase)
      (*print-right-margin* 50))
  (pprint
   (ppcre:parse-string "^(?:([A-Za-z]+):)?(\\/{0,3})(0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$")))

... ve aşağıdaki biçimde sonuçlanır:

(:sequence :start-anchor
 (:greedy-repetition 0 1
  (:group
   (:sequence
    (:register
     (:greedy-repetition 1 nil
      (:char-class (:range #\A #\Z)
       (:range #\a #\z))))
    #\:)))
 (:register (:greedy-repetition 0 3 #\/))
 (:register
  (:sequence "0-9" :everything "-A-Za-z"
   (:greedy-repetition 1 nil #\])))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\:
    (:register
     (:greedy-repetition 1 nil :digit-class)))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\/
    (:register
     (:greedy-repetition 0 nil
      (:inverted-char-class #\? #\#))))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\?
    (:register
     (:greedy-repetition 0 nil
      (:inverted-char-class #\#))))))
 (:greedy-repetition 0 1
  (:group
   (:sequence #\#
    (:register
     (:greedy-repetition 0 nil :everything)))))
 :end-anchor)

Bu sözdizimi daha ayrıntılıdır ve aşağıdaki yorumlara bakarsanız, mutlaka daha okunaklı olması gerekmez. Bu nedenle, daha az kompakt bir sözdiziminiz olduğundan, işlerin otomatik olarak daha net olacağını varsaymayın .

Bununla birlikte, normal ifadelerinizde sorun yaşamaya başlarsanız, bunları bu formata dönüştürmek kodunuzun şifresini çözmenize ve hata ayıklamanıza yardımcı olabilir. Bu, tek karakterli bir hatanın tespit edilmesinin zor olabileceği string tabanlı formatlara göre bir avantajdır. Bu söz diziminin en büyük avantajı , dizge tabanlı bir kodlama yerine yapısal bir format kullanarak normal ifadeleri değiştirmektir. Bu, programınızdaki diğer veri yapıları gibi ifadeleri oluşturmanıza ve oluşturmanıza olanak sağlar . Yukarıdaki sözdizimini kullandığımda, bunun nedeni genellikle daha küçük parçalardan ifadeler oluşturmak istediğimdir (ayrıca bkz . CodeGolf cevabım ). Örneğin, 1 yazabiliriz :

`(:sequence
   :start-anchor
   ,(protocol)
   ,(slashes)
   ,(domain)
   ,(top-level-domain) ... )

Dizi tabanlı düzenli ifadeler, dizi birleştirmeyi ve yardımcı fonksiyonlara sarılmış enterpolasyonu kullanarak da oluşturulabilir. Ancak eğilimi dize manipülasyonlar ile sınırlamalar vardır yığılmayı kodu (değil ters tırnakların aksine vs yuvalama sorunları düşünmek $(...)bash; ayrıca, karakterlerin baş ağrısı verebilir kaçış).

Ayrıca yukarıdaki formun (:regex "string")formlara izin verdiğine dikkat edin, böylece veciz notasyonlarını ağaçlarla karıştırabilirsiniz. Tüm bunlar IMHO'ya iyi okunabilirlik ve beste kabiliyetine yol açmaktadır; delnan tarafından dolaylı olarak ifade edilen üç sorunu ele almaktadır (yani, düzenli ifadelerin dilinde değildir).

Sonuçlandırmak

  • Çoğu amaç için, kısa nota aslında okunabilir. Geriye dönük izlemeyi içeren genişletilmiş notasyonlarla uğraşırken zorluklar var, ancak bunların kullanımı nadiren haklı. Düzenli ifadelerin haksız kullanımı, okunamayan ifadelere yol açabilir.

  • Normal ifadelerin dizge olarak kodlanması gerekmez. Düzenli ifadeler oluşturmanıza ve oluşturmanıza yardımcı olacak bir kitaplığınız veya aracınız varsa, dize işlemleriyle ilgili birçok olası hatadan kaçınırsınız .

  • Alternatif olarak, biçimsel gramerler daha okunaklıdır ve alt ifadeleri adlandırma ve özetlemede daha iyidir. Terminaller genellikle basit düzenli ifadeler olarak ifade edilir.


1. İfadelerinizi okuma zamanında oluşturmayı tercih edebilirsiniz, çünkü normal ifadeler bir uygulamada sabit olma eğilimindedir. Bakınız create-scannerve load-time-value:

'(:sequence :start-anchor #.(protocol) #.(slashes) ... )

5
Belki de sadece geleneksel RegEx sözdizimine alışkınım, ama 22 okunaklı satırın anlaşılması zor bir satır regex'inden daha kolay olduğundan emin değilim.

3
Eğer gerçekten uzun regex olması gerekiyorsa @ dan1111 "biraz okunabilir" ;-) Tamam, ama bu gibi alt kümelerini, tanımlanması mantıklıdır digits, identve bunları oluşturur. Yaptıklarını gördüklerim, genellikle doğru kaçış gibi başka problemler getiren dize manipülasyonları (birleştirme veya enterpolasyon) ile oluyor. \\\\`Örneğin, emacs paketlerinin oluşumlarını arayın . Aynı kaçış karakteri gibi özel karakterler için hem kullanıldığı için Btw, bu kötü yapılmış \nve \"ve regex sözdizimi için \(. Lisp olmayan, iyi bir sözdizimi örneği, çatışmanın olmadığı printfyerdir . %d\d
coredump

1
tanımlanmış alt kümeler hakkında adil nokta. Bu çok mantıklı. Ben sadece ayrıntıların bir gelişme olduğu konusunda şüpheliyim. Yeni başlayanlar için daha kolay olabilir (gibi kavramlar greedy-repetitionsezgisel değildir ve yine de öğrenilmeleri gerekir). Bununla birlikte, uzmanlar için kullanılabilirliği feda eder, çünkü tüm modeli görmek ve kavramak çok zordur.

@ dan1111 Ayrıntıların tek başına bir gelişme olmadığı konusunda hemfikirim. Bir gelişme olabilir, dizge yerine yapılandırılmış veri kullanarak regex'i değiştirmek.
coredump

@ dan1111 Belki Haskell kullanarak bir düzenleme önermeliyim? Parsec bunu sadece dokuz satırda yapıyor; tek astar olarak: do {optional (many1 (letter) >> char ':'); choice (map string ["///","//","/",""]); many1 (oneOf "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-."); optional (char ':' >> many1 digit); optional (char '/' >> many (noneOf "?#")); optional (char '?' >> many (noneOf "#")); optional (char '#' >> many (noneOf "\n")); eof}. Uzun bir dize atamak gibi birkaç satır ile domainChars = ...ve section start p = optional (char start >> many p)oldukça basit görünüyor.
CR Drost,

25

Regex'le ilgili en büyük problem aşırı ters sözdizimi değildir, karmaşık bir tanımı daha küçük yapı taşlarından oluşturmak yerine tek bir ifadeyle ifade etmeye çalışıyoruz. Bu, hiçbir zaman değişkenleri ve işlevleri kullanmadığınız ve bunun yerine kodunuzu tek bir satıra gömdüğünüz programlamaya benzer.

Regex'i BNF ile karşılaştırın . Sözdizimi, regex'ten çok daha temiz değildir, ancak farklı şekilde kullanılır. Basit adlandırılmış semboller tanımlayarak başlar ve eşleştirmek istediğiniz tüm deseni tanımlayan bir sembole gelinceye kadar bunları oluşturur.

Örneğin, rfc3986'daki URI sözdizimine bakın :

URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
hier-part     = "//" authority path-abempty
              / path-absolute
              / path-rootless
              / path-empty
...

Neredeyse aynı şeyi, adlandırılmış alt ifadeleri yerleştirmeyi destekleyen regex sözdiziminin bir türevi kullanarak yazabilirsiniz.


Şahsen ben sözdizimi gibi kısa bir regex'in karakter sınıfları, birleştirme, seçim veya tekrarlama gibi yaygın olarak kullanılan özellikler için iyi olduğunu düşünüyorum; Oldukça benzer , normal programlama gibi +veya gibi operatörleri kullanmaya *ve daha nadir işlemler için adlandırılmış fonksiyonlara geçmemize benzer.


12

selfDocumentingMethodName (), e () işlevinden çok daha iyidir

bu mu? Birçok dilin BEGIN ve END yerine blok sınırlayıcı olarak {ve} olmasının bir nedeni vardır.

Kişiler durgunluktan hoşlanır ve sentaksı bir kere öğrenirsen, kısa terminoloji daha iyidir. Eğer regex örneğinizi d (rakam için) 'rakam' ise, regex'in okumak için daha da korkunç olacağını düşünün. Kontrol karakterleriyle daha kolay ayrıştırılabilir olsaydı, XML gibi görünürdü. Sen de bir sentaksiyi bilsen ne kadar iyi olmaz

Sorunuzu doğru bir şekilde cevaplamak için, regex'in açıklığın zorunlu olduğu günlerden geldiğini anlamalısınız. Bugün 1 MB'lık bir XML belgesinin çok önemli olmadığını düşünmek kolaydır, ancak 1 MB'lık bir gün olduğu zamanlar hakkında konuşuyoruz. tüm depolama kapasiteniz. O zaman kullanılan daha az dil vardı ve regex perl veya C'den bir milyon mil uzakta değildi, bu yüzden sözdizimi sözdizimini öğrenmekle mutlu olacak olan günün programcılarına aşina olacaktı. Bu yüzden daha ayrıntılı hale getirmek için hiçbir sebep yoktu.


1
selfDocumentingMethodNameGenel olarak, programcı sezgisinin gerçekte okunabilirlik veya iyi kalite kodu neyin oluşturduğuna ilişkin olarak gerçeğe uygun olmadığından daha iyi olduğu kabul edilir . Kabul eden insanlar yanlıştır, ama bu böyle. e
Leushenko

1
@Leushenko: Bunun e()daha iyi olduğunu selfDocumentingMethodName()mu iddia ediyorsunuz ?
JacquesB

3
@JacquesB belki de tüm bağlamlarda (küresel bir isim gibi) değil. Ama sıkıca kapanan şeyler için? Neredeyse kesin. Kesinlikle geleneksel bilgeliğin söylediğinden daha sık.
Leushenko

1
@Leushenko: Bir bağlamın, tek bir harf işlevi adının daha açıklayıcı bir addan daha iyi olduğunu hayal etmekte zorlanıyorum. Ama sanırım bu saf bir görüş.
JacquesB

1
@MilesRout: Örnek aslında e()kendi kendini belgeleme yöntemi adına göre. Tanımlayıcı yöntem adları yerine tek harfli yöntem adlarını kullanmanın hangi bağlamda bir gelişme olduğunu açıklayabilir misiniz?
JacquesB

6

Regex lego parçaları gibidir. İlk bakışta, birleştirilebilecek farklı şekilli plastik parçalar görüyorsunuz. Biçimlendirebileceğiniz çok fazla farklı şey olmayacağını düşünebilirsiniz, ancak diğer insanların yaptığı inanılmaz şeyleri görürsünüz ve ne kadar harika bir oyuncak olduğunu merak edersiniz.

Regex lego parçaları gibidir. Kullanılabilecek birkaç argüman var, ancak bunları farklı formlarda zincirleme birçok karmaşık iş için kullanılabilecek milyonlarca farklı regex modelini oluşturacak.

İnsanlar nadiren yalnızca regex parametrelerini kullanırlar. Birçok dil, bir dizgenin uzunluğunu kontrol etme veya sayısal parçaları ondan ayırma işlevlerini sunar. Metinleri dilimlemek ve yeniden biçimlendirmek için string işlevlerini kullanabilirsiniz. Çok belirli karmaşık işler yapmak için karmaşık formlar kullandığınızda regex'in gücü fark edilir.

SO'da on binlerce regex sorusu bulabilirsiniz ve nadiren kopyalanmış olarak işaretlenirler. Sadece bu, birbirinden çok farklı olan olası benzersiz kullanım durumlarını gösterir.

Ve bu kadar farklı benzersiz görevleri yerine getirmek için önceden tanımlanmış yöntemler sunmak kolay değildir. Bu tür görevler için string işlevlerine sahipsiniz, ancak bu işlevler specix göreviniz için yeterli değilse, o zaman regex kullanma zamanı gelmiştir.


2

Bunun potansiyel olmaktan çok bir uygulama sorunu olduğunu biliyorum. Sorun genellikle , bileşik ifadeler varsaymak yerine, düzenli ifadeler doğrudan uygulandığında ortaya çıkar . Benzer şekilde, iyi bir programcı, programının işlevlerini kısa ve öz yöntemlere ayırır.

Örneğin, bir URL için regex dizgisi yaklaşık olarak düşürülebilir:

UriRe = [scheme][hier-part][query][fragment]

için:

UriRe = UriSchemeRe + UriHierRe + "(/?|/" + UriQueryRe + UriFragRe + ")"
UriSchemeRe = [scheme]
UriHierRe = [hier-part]
UriQueryRe = [query]
UriFragRe = [fragment]

Düzenli ifadeler çok güzel şeylerdir, ancak görünürde karmaşıklığıyla emilenlerin istismarı vardır . Ortaya çıkan ifadeler, uzun vadeli bir değer bulunmayan retoriktir.


2
Ne yazık ki çoğu programlama dili, regex oluşturmada yardımcı olan işlevleri içermez ve grup yakalamanın çalışma şekli de kompozisyon oluşturmak için çok kolay değildir.
CodesInChaos 30:15

1
Diğer dillerin "perl uyumlu düzenli ifade" desteğinde Perl 5'e yetişmeleri gerekir. Alt ifadeler, yalnızca regex belirtim dizelerinin birleştirilmesiyle aynı değildir. Yakalamalar, örtülü numaralandırmaya dayanarak adlandırılmalıdır.
JDługosz 30:15

0

@Cmaster'ın dediği gibi, regexps başlangıçta sadece anında kullanılmak üzere tasarlandı ve satır gürültüsü sözdiziminin hala en popüler olanı olması tuhaf (ve biraz iç karartıcı). Atalet, mazoşizm ya da machismo ile ilgili düşünebileceğim tek açıklamalar (sık sık 'atalet' bir şeyi yapmanın en çekici nedeni değildir…)

Perl, boşluk ve yorumlara izin vererek onları daha okunaklı hale getirmek için oldukça zayıf bir girişimde bulunuyor, ancak uzaktan yaratıcı bir şey yapmıyor.

Başka sözdizimleri de var. En iyisi , benim deneyimime göre yazması oldukça kolay olan ancak gerçekte okunabilir olan regexps üreten regexps için scsh sözdizimidir .

[ scsh , sadece biri ünlü onay metni olan, başka nedenlerden dolayı muhteşem ]


2
Perl6 yapar! Dilbilgisine bak.
JDługosz

@ JDługosz Gördüğüm kadarıyla, normal ifadeler için alternatif bir sözdiziminden ziyade, çözümleyici üreticiler için bir mekanizmaya benziyor. Ancak ayrım belki de derin değildir.
Norman Grey

Bir yedek olabilir, ancak aynı güçle sınırlı değildir. Regedp'i, değiştiricilerin 1 ila 1 yazışmalarıyla ancak daha okunabilir bir sözdiziminde satır içi gramerine çevirebilirsiniz. Bunu teşvik eden örnekler orijinal Perl Kıyamet Günü'ndedir.
JDługosz 30:15

0

Düzenli ifadelerin "genel" ve mümkün olduğunca basit olacak şekilde tasarlandığından inanıyorum, bu yüzden (kabaca) her yerde aynı şekilde kullanılabilirler.

Siz örneğin, regex.isRange(..).followedBy(..)belirli bir programlama dilinin sözdizimine ve belki de nesne yönelimli stile (yöntem zincirleme) bağlandınız.

Bu kesin 'regex' örneğin C'ye nasıl bakar? Kodun değiştirilmesi gerekecekti.

En 'genel' yaklaşım, daha sonra herhangi bir başka dile değişmeden kolayca gömülebilen basit ve özlü bir dil tanımlamaktır. Ve bu (neredeyse) regex nedir.


0

Perl-Uyumlu Düzenli İfade motorları yaygın olarak kullanılır ve birçok editörün ve dilin anladığı düzenli ve düzenli bir ifade sözdizimi sağlar. @ JDługosz'un yorumlarda belirttiği gibi, Perl 6 (sadece Perl 5'in yeni bir sürümü değil, tamamen farklı bir dil), düzenli ifadeleri ayrı ayrı tanımlanmış öğelerden oluşturarak daha okunaklı hale getirmeye çalıştı. Örneğin, Wikibook’lardan URL’leri ayrıştırmak için örnek bir dilbilgisi :

grammar URL {
  rule TOP {
    <protocol>'://'<address>
  }
  token protocol {
    'http'|'https'|'ftp'|'file'
  }
  rule address {
    <subdomain>'.'<domain>'.'<tld>
  }
  ...
}

Düzenli ifadenin bu şekilde bölünmesi, her bitin ayrı ayrı tanımlanmasına (örn domain. Alfanümerik olmasını engelleme) veya alt sınıflandırma (örneğin yalnızca FileURL is URLbu kısıtlamalar ) yoluyla genişletilmesine izin protocolverir "file".

Öyleyse: hayır, düzenli ifadelerin netliği için teknik bir neden yoktur, ancak bunları ifade etmenin daha yeni, daha temiz ve daha okunaklı yolları zaten burada! Öyleyse bu alanda bazı yeni fikirler göreceğiz.

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.