Perché le espressioni regolari sono così morbosamente attraenti?


23

Allegato 1 , Allegato 2 , immagino che non ti sarà difficile ricordare altri esempi.

La cosa è: se esiste più di un modo per risolvere un problema, il programmatore PHP (di solito sfoglio il tag PHP su StackOverflow) chiederà aiuto sulla soluzione che coinvolge espressioni regolari.

Anche quando sarà meno economico, anche quando il manuale di php suggerisce ( link ) di usare al str_replaceposto di qualsiasi preg_*o ereg_*funzione quando non sono richieste regole di sostituzione fantasiose.

Qualcuno ha la minima idea del perché questo accada?

Non fraintendetemi, alcuni dei miei migliori amici sono espressioni regolari e non disprezzo Perl. Quello che non capisco è perché non si cercano alternative, anche quando l'overkill è evidente (regex per cambiare le stringhe) o la complessità del codice aumenta esponenzialmente (regex per ottenere dati da HTML in PHP )


2
Potresti voler citare ciò che dice il manuale di php.
ChrisF

1
Perché sono criptici, quindi vuoi far parte dell'esclusivo club di Kewl Kidz? E soprattutto perché forniscono un modo breve per esprimere una corrispondenza o estrazione, che è ciò per cui sono fatti. Certo per casi fittizi, analisi personalizzata se meglio, ma il tempo di sviluppo rispetto alla scrittura di una rapida regex è a favore della regex.
Hayylem

Hai sottolineato la parte sbagliata di quest'ultima frase: la parte scandalosa di essa è "da HTML", non "in PHP".
Izkata

Risposte:


20

Perché le espressioni regolari sono così morbosamente attraenti?

Perché a livello di subconscio si sentono come un intero programma intelligente che può realizzare molto da solo, pur essendo avvolgente e autoregolante (schemi di pensiero).

Questo è il motivo per cui le persone credono immediatamente che le espressioni regolari risolveranno qualsiasi loro compito basato sul testo, in qualche modo non pensando che potrebbe essere eccessivo e non rendermi conto che potrei essere insufficiente (analizzando le lingue con esso).

Una piccola cosa contenente potere magico. Non puoi dire di no, vero?


5
+1 - Una piccola cosa criptica , non meno.
AJ Johnson,

Gli hobitses sono complicati
Ben DeMott

49

Quando l'unico strumento che hai è una regex, ogni problema sembra ^((?>[a-zA-Z\d!#$%&'*+\-/=?^_{|}~]+\x20*|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)(?>\.?[a-zA-Z\d!#$%&'*+\-/=?^_{|}~]+)+|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d)){4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^\\\[\]]|\\[\x01-\x7f])+)\])(?(angle)>)$


16
La tentazione di scegliere questa risposta è così forte, ma credo di dover resistere dato che è la mia prima domanda aperta qui e devo fingere la serietà per un po '.
cbrandolino,

1
@Dev, ha molto senso. Il mio commento è stato solo un modo apparentemente divertente per esprimere il mio apprezzamento per la risposta.
cbrandolino,

17
Cosa diavolo corrisponde?
Tom O'Connor,

4
Non lo so ... Penso che questo riassuma praticamente tutto. Se conosci regex e non conosci gli altri metodi, perché dovresti cercare? Hai già uno strumento che, se fatto correttamente, gestirà il lavoro. Fino a quando non si imbatteranno nel metodo più semplice o non ne verranno informati, regex sarà il metodo catch-all, anche se più complesso di quanto sia necessario.
Aeo,

4
@Tom O'Connor Penso che sia qualcosa di simile al Regex per abbinare un indirizzo e-mail RFC 2822, ma ho dovuto eliminare un paio di personaggi perché stavano causando il caos con il markdown.
glenatron,

23

Penso che sia perché:

  1. Sono fantasticamente concisi (se usati correttamente) rispetto al codice equivalente, e
  2. Sono ampiamente supportati in tutti i linguaggi di programmazione, quindi la maggior parte degli sviluppatori ne ha familiarità.

3
# 2 ha senso.
cbrandolino,

23

Nelle fasi precedenti della mia carriera (cioè pre-PHP), ero un guru del Perl, e un aspetto importante del gurudom del Perl è la padronanza delle espressioni regolari.

Nella mia squadra attuale, sono letteralmente l'unico di noi che cerca regex prima di altri strumenti (di solito più cattivi). Sembra che per il resto della squadra siano pura magia. Si avvicineranno alla mia scrivania e mi chiederanno una regex che mi impiega letteralmente dieci secondi per essere messa insieme, e poi sarà spazzata via quando funziona. Non lo so - ho lavorato con loro così a lungo, è naturale a questo punto.

In assenza di fluidità regex, ti rimangono combinazioni di istruzioni di controllo del flusso che avvolgono le istruzioni strstr e strpos, che diventano brutte e difficili da eseguire nella tua testa. Preferirei di gran lunga creare un'elegante regex piuttosto che trenta righe di ricerca di stringhe in movimento.


2
Non posso votare abbastanza.
CaffGeek,

8
Sono curioso: leggi regexp con la stessa fluidità con cui li scrivi?
Peter

7
Spero che tu stia tenendo regolari sessioni di addestramento regex e / o documentando l'inferno dal tuo codice; altrimenti stai creando un incubo di supporto per i tuoi colleghi. Il tempo che hai risparmiato scrivendo che regex può essere perso cento volte dalle persone che cercano di capire cosa sta facendo quell'elegante regex.
Jeff Knecht

3
Fantastico Puoi sentire il tiro alla fune tra regex amare e odiare proprio qui in questi commenti.
Dan Ray

1
@Ben Lee: Immagino di sì - OTOH, non ho mai incontrato una regex commentata in natura. Alcuni dei problemi con le regex possono essere basati su un atteggiamento di freddezza.
Peter

16

Anzi. Le persone stanno pappagallando il regex sono meme malvagie troppo spesso IMO. È ovvio che preg_match è abusato php, ma è meno ovvio che spesso è ragionevole farlo (in PHP).

Andrei così lontano e congetture che è ancora un'altra microottimizzazione nella terra del php per usare le funzioni di stringa. Ci sono molti e molti utili, e di solito sono la scelta migliore. Ma non dovresti evitare preg_matcha favore di multipli strpose ifcatene. Perché in pratica si scopre che libpcre è spesso più veloce di quanto PHP possa eseguire un loop alla ricerca di alternative di stringa, ad es

Come un recente esempio mi ha fatto capire, testando se una stringa è tutta in minuscolo:

 if ($string == strtolower($string))

È più leggibile di:

 if (!preg_match("/[A-Z]/", $string))

E supponeresti che il primo debba essere più veloce, dal momento che è tutto-PHP. Ma in realtà il regex osserva una volta la stringa e può interrompere la condizione negata non appena trova una lettera maiuscola. L'approccio strtolower () tuttavia osserva due volte la stringa. Primo strtolower () crea una stringa duplicata ripetendo ripetutamente ogni lettera, confrontandola e aumentandola. Quindi ==scorre nuovamente l'originale e la copia, confrontandoli ancora una volta.

Quindi non è un caso ovvio. E per essere oggettivi il primo è spesso più veloce, dal momento che normalmente si confrontano solo stringhe corte. Ma è indispensabile non andare alla cieca supponendo che le funzioni di stringa PHP siano sempre consigliate rispetto alle espressioni regolari.

(Sono tentato di aggiungere un altro rant sulla risposta divertente di @ bobince per quanto riguarda le regex xhtml, e come recentemente è spesso collegato in modo molto inutile. E le risposte più obiettive sotto vengono ignorate.)


1
Sono d'accordo con il tuo esempio; tuttavia, in questo caso particolare, preferirei comunque "Strtolower ()": nel codice non critico, anche un'ottimizzazione dei tempi di esecuzione così grande (relativamente all'altra implementazione) è insignificante - a meno che tu non voglia valutare il minuscolo - l'essenza di un enorme file di testo, ma non riesco a immaginare un caso in cui sarebbe utile.
cbrandolino,

1
@cbrandolino: nessuna discussione lì. Questa roba dovrebbe essere pertinente e valutata solo per i cicli nidificati, dove potrebbe fare la differenza.
Mario,

4
+1 Per il fatto che le persone li colpiscono sempre, molto più di quanto siano supportati.
Orbling

1
Come uno dei "regexp bashers": è divertente vedere un one-liner più o meno esprimere ciò per cui la stringa "manuale" analizza nedds 30 righe. Tuttavia, la manutenzione soffre negli esempi più realistici. Inoltre, quando si tenta di applicarli a input non convalidati, la generazione di una diagnostica adeguata per input rifiutato richiede acrobazie aggiuntive. Per me, è il prototipo del codice "solo scrittura": fantastico per gli script veloci, fa schifo per le app di lunga durata.
Peter

1
Chiunque non stia scrivendo tutte le sue regex in /xmodalità per consentire spazi bianchi per il gomito del chunking cognitivo e per i commenti per spiegare perché le cose vengono fatte, ovviamente dovrebbero avere le orecchie chiuse. Ma per reali regex di ragionevole complessità, è necessario considerare l'applicazione del design top-down tramite regex grammaticali . Una volta che hai visto la luce, non tornerai più a /@#$^^@#$^&&*)@#/.
tchrist

8

Le espressioni regolari sono molto interessanti perché sono lo strumento migliore per analizzare una lingua normale.

Hanno i seguenti vantaggi:

  • Sono concisi . In genere ci vuole molto più codice per analizzare un linguaggio regolare specifico usando un algoritmo specifico che hai creato che con un regexp.
  • Sono veloci da usare. Generalmente ci vuole molto più tempo per scrivere un parser per un linguaggio specifico specifico usando un algoritmo specifico che hai creato che con un regexp.
  • Sono facili . Dopo aver appreso l'insieme di caratteri speciali e il loro significato, è facile comporre una regexp (anche se un po 'più difficile da leggerli). I regexps sono le lingue stesse - un tratto utile perché la nostra specie si è evoluta per essere molto brava nel linguaggio.
  • Sono veloci . Una volta compilati, possono corrispondere a una lunghezza della stringa Nnel tempo O ( N).
  • Sono flessibili . Possono corrispondere a qualsiasi lingua normale e molti dei nostri dati sono espressi come lingua normale.
  • Sono onnipresenti . La maggior parte dei linguaggi di programmazione ha il supporto regexp di base - tramite librerie esterne o incorporate nel linguaggio stesso. Inoltre non c'è troppa variazione tra le lingue regexp stesse.

Questo li rende attraenti per le situazioni in cui sono adatti, ma le persone possono usarli in contesti in cui non sono lo strumento migliore, perché:

  • Non capisco che ciò che stanno abbinando non può essere espresso usando un regexp (es. HTML).
  • Sono pigri (in senso negativo): conoscono uno strumento e riconoscono che non è lo strumento migliore per quello che stanno facendo, ma funzionerà senza problemi il 95% delle volte e impiegherà il 95% dello sforzo di apprendere un particolare parser o scriverne uno da zero.
  • Non sono consapevoli dell'esistenza di strumenti migliori.

Ehm, mi riferivo ad alcuni casi particolari in cui evidentemente non sono il modo migliore di procedere ma sono ancora usati. Mi piace regex (voglio dire, li trovo noiosi e senza vita, ma comunque molto utili in alcuni contesti), e so quali sono i loro vantaggi.
cbrandolino,

Concordo con il resto, ma veloce e facile? La curva di apprendimento è ripida: per un principiante, è difficile capire perché un'espressione non funziona e ogni attrezzo regexp sembra avere differenze almeno sottili, quindi devi fare attenzione a dove provi ad imparare.
Peter

Perché tutti confondono estraendo piccoli frammenti di HTML con l'analisi completa di una pagina Web completa in un albero di analisi completo? È davvero stupido. Credimi, quando modifico le pagine HTML vi, scommetti la tua vita che uso :%s/foo/bar/gcsu di essa. Se è abbastanza buono per un editor, è abbastanza buono per uno script.
tchrist

6

Hmmm, posso solo immaginare. Forse alcune persone hanno sperimentato che 30 righe del loro codice sono state sostituite da una regex di 20 caratteri, quindi è sbagliato usare qualcos'altro invece quando si possono usare le regex.


4

Si adatta a come pensano alcune persone. Non mi piacciono, ma ho amici che sembrano pensare in regexps. Immagino che il modello corrispondente alla parte del loro cervello sia più esposto di quello logico formale. :-)


6
In termini della nostra storia evolutiva che resiste alla ragione. Stavamo abbinando schemi molto prima di definire grammatiche o scoprire sillogismi.
glenatron,

1
Non sono d'accordo, la programmazione prevede la logica e la corrispondenza dei modelli, due aree. I regexps sono molto bravi nella corrispondenza dei modelli e dovrebbero essere usati per tali compiti. Dire anche "Non mi piacciono" è buttare via un buon strumento per un determinato lavoro.
Orbling

@Orbling: la domanda non è se siano buoni o cattivi, ma perché alcune persone li abusano e altri no.
Lennart Regebro,

La domanda potrebbe essere, ma la tua risposta suggerisce che l'uno o l'altro tipo di mente è in gioco, piuttosto che entrambi.
Orbling

Non credo che "suggerire" sia la parola corretta.
Lennart Regebro,

3

Penso che l'ubiquità di regex sia dovuta all'ubiquità delle stringhe. La stringa è la struttura dati più semplice, la prima che la maggior parte di noi impara. Poiché tutto il nostro codice è scritto in forma simbolica, è naturale per un programmatore considerare la modellazione di qualcosa in forma simbolica. Ma se il nostro linguaggio di programmazione offre qualche resistenza quando proviamo ad estendere la sua sintassi per le nostre nuove intelligenti forme simboliche, finiscono tutte tra virgolette. Il modello di dati relazionali ha SQL. Il modello di dati XML ha XQuery. Ma per quanto riguarda l'umile modello di dati di stringa? Regex!

Proprio ieri, stavo cercando l'API per un nuovo brillante framework Javascript che supporti lo sviluppo di giochi HTML5. Ha un meccanismo dichiarativo per descrivere i principali sottosistemi di cui il tuo gioco avrebbe bisogno. Come si specificano queste funzionalità? JSON? Notazione fluida del punto? Un array? No: una stringa contenente un elenco di nomi di funzioni separati da virgola e spazi bianchi. Mi chiedo come analizza quell'elenco ...?


2

Perché puoi vedere tutto in una volta. Potendo vedere tutto, può essere più facile lavorare con, ed è sempre bello. È un po 'come la ragione per cui molti programmatori C ++ usano ancora istruzioni di tipo printf: non è typesafe (anche se gcc almeno può controllare i tipi su istruzioni printf), e non è carino, ma ragazzo è compatto e utilizzabile.

Se è una regex abbastanza semplice, spesso SONO il modo migliore per fare le cose - la loro forma compatta e molte capacità li rendono perfetti per determinati compiti. Il problema si presenta quando rendi il regex così complicato da non poterlo più leggere o quando stai usando un regex complesso per fare qualcosa che potrebbe essere fatto più rapidamente tramite semplici operazioni su stringa.

Regex, come qualsiasi altro potente strumento, deve essere usato con la giusta moderazione - non troppo, non troppo poco. E a meno che le prestazioni non siano una grande preoccupazione, a volte un singolo regex può essere più veloce da scrivere e più facile da eseguire il debug di una serie di operazioni sulle stringhe.


2

Hmm, le risposte attuali si concentrano troppo sugli aspetti tecnici e sui pro / contro della leggibilità (che è un punto importante). Vorrei quindi provare a spostarlo un po 'di più sull'ambiente / comunità PHP:

  • PHP è la sorellastra di Perls . E una parte integrante del Perl sono le espressioni regolari (hanno inventato quella roba, vero?). Pertanto è una delle cause per cui i regexps sono pervasivi anche in PHP.
  • Per caso, il caso d' uso di PHP non è molto diverso dal caso d'uso per le espressioni regolari. PHP è utilizzato strutturalmente per incollare insieme pagine HTML. E regexps lavora sul testo. (cosa ha detto WReach)
  • Micro ottimizzazione . Come accennato in precedenza: le persone usano regexps e / o funzioni di stringa PHP frequentemente dopo la velocità percepita. Un problema fondamentale nei circoli PHP, non specifico per regexps.
  • Le espressioni regolari sono integrate . In Python, in Java, in C #, in Ruby? c'è disponibilità, ma un deterrente nel dover caricare un modulo aggiuntivo. E vedi come in PHP o Javascript, dove si trova una caratteristica principale, il modello di utilizzo differisce. Un'altra mostra: CSS dove viene utilizzato più frequentemente.
  • Il manuale di PHP è in errore. Lo è spesso. Le espressioni regolari sono facilmente individuabili e ho rinviato questo fatto divertente perché è noioso nella sua ovvietà: tutti i dannati tutorial e i libri di introduzione a PHP insegnano sempre sulle espressioni regolari, ma non riescono a educare sui casi d'uso.
  • L' API di stringa in PHP è stata progettata dalle stesse persone che ti hanno portato virgolette magiche e lo spazio dei nomi \ separatore. È avvolgente, migliore di Java, ma non affascinante nella sua interezza. Soprattutto se le stringhe potrebbero raddoppiare come oggetti (vedi Python), le funzioni di stringa potrebbero superare regexps.

Ma proprio come note a margine. Credo che siano in gran parte ragioni percettive e tecniche che portano a un uso eccessivo e / o ad evitare espressioni regolari in generale. Eppure PHP e la sua base utenti hanno alcune proprietà che lo compongono, e perché vediamo più domande su SO al riguardo [citazione necessaria!] E sono "morbosamente attraenti" lì.


1

Mi piacciono le espressioni regolari in generale, le trovo più facili da leggere / comprendere rispetto alle 20 righe di codice che dovrei sostituirle. Le espressioni regolari brevi vengono lette e comprese rapidamente e sono relativamente facili da mantenere (se l'espressione cambia, hai solo una riga da cambiare rispetto a guardare attraverso le 20 righe di codice per apportare la modifica). Ci sono momenti in cui vengono usati in modo improprio, ma lo sono anche molte altre cose.

Il motivo per cui probabilmente ne vedi così tanti abusi è perché stai navigando nella sezione PHP di StackOverFlow poiché sono sicuro che sei consapevole che ci sono molti programmatori PHP umm immaturi là fuori.


1

Perché le espressioni regolari sono così morbosamente attraenti?

Loro non sono. Sono davvero brutti da morire. E incomprensibile. Sono un abominio che dovrebbe essere ucciso il prima possibile.

Ora, detto questo, tornerò al debug di una piccola app Perl. Non posso farci niente; sfortunatamente, a volte sono ancora lo strumento migliore per il lavoro.


4
Mi piace dire che le espressioni regolari non sono né "regolari" né "espressive"
Andrew Barber,

2
Sono brutti e incomprensibili se non li capisci. Una volta raggiunto lo zen di regex, sono davvero abbastanza eleganti.
Dan Ray,

1
-1 Per aver deciso che a tutti i programmatori piace essere oscuri, e quindi non considerare altre possibili spiegazioni. ... Dichiarare perché pensi che siano brutti o incomprensibili avrebbe aiutato.
Macneil,

1
@Macneil - Per favore, (anche se sì, i miei pensieri sono su quella linea), a meno che tu non mi stia citando non affermare che ho detto / deciso su qualcosa che non ho fatto (la prima parte del tuo commento). Per quanto riguarda la tua domanda, li trovi belli ?! ... Io non. E poiché questo è un sito soggettivo, e questa è un'opinione soggettiva, non devo né desidero approfondire. Né ci proverò, del resto.
Rook,

1
@Rook - Penso che la maggior parte delle persone guardi un'espressione regolare complessa, decida che tutte le espressioni regolari sono brutte e poi smettono di pensare. Il fatto è che sono uno strumento molto elegante ed espressivo se puoi esprimere il tuo pregiudizio su di loro. A proposito, secondo la tua logica, molti programmatori non possono fare l'algebra, quindi l'algebra è probabilmente intrinsecamente malvagia e dovrebbe essere abolita poiché chiaramente non è molto comprensibile.
Dan Ray,

0

L'uomo è una creatura che usa strumenti e le espressioni regolari sono strumenti potenti. Una bella metafora per le espressioni regolari è un'affettatrice da carne di una gastronomia. Se vuoi fette sottili di carta di tacchino, carne in scatola, ecc., È la cosa giusta. Tuttavia, hai bisogno di mani esperte per usarlo, perché puoi tagliarti davvero male e non sentirai nulla finché non vedrai il sangue. Ciò che intendo con questo è che il grosso problema delle espressioni regolari è quello di toglierle leggermente significa che abbini qualcosa che non dovresti, o viceversa, e non lo scopri fino a quando non causa un problema più avanti nel processo.


0

Le espressioni regolari sono molto attraenti perché esercitano potere. Puoi fare un lavoro molto complicato in pochissimi personaggi.

Il problema è che il costrutto standard delle espressioni regolari non è completo di Turing, il che significa che ci sono programmi che semplicemente non puoi implementare con un'espressione regolare, e le persone non lo sanno quando sono attirati dal potere apparente delle espressioni regolari.

Questo - suppongo - è il motivo della citazione jwz di "ora hanno due problemi".

Mi immagino che Perl espressioni regolari sono Turing-completo, ma a quanto pare non è stato decisamente provata o smentita ancora.


0

Perché è un modo efficiente per programmare una macchina a stati finiti, che è uno strumento potente quando si applica. Fondamentalmente è la propria lingua per la programmazione degli FSM, il che è utile se si conosce la lingua, fastidioso in caso contrario.


0

Nella mia esperienza, le regex sono come un'arte antica, qualcosa di oscuro, alcune persone le risentono perché non riescono a capire la stregoneria coinvolta e forse perché nessuno te le spiegherà. Non ho sentito parlare di università che insegnano loro per qualcosa di meno banale che abbinare una e-mail. Poi c'è il mistico funzionamento interiore di esso, poiché la maggior parte delle persone non li capisce, devono essere lenti . E farli funzionare bene al primo tentativo è sempre una sfida per i nuovi arrivati.

La stessa cosa si può dire di Perl, awk, Linux e di tutto ciò che non ha pulsanti lucidi o una bella sintassi colorata. Quindi, è come una maggiore complessità per "compiti banali", basta lanciare alcuni anelli, divisioni, un interruttore, un po 'di magia e basta, qualcosa che potrebbe funzionare. Ma bene, se ti trovi dall'altra parte della strada, le regex sono bellissime formine per biscotti che sembrano rumori di segnale senza brutti loop o altro materiale da sottoporre a debug. Mi piacciono anche per la flessibilità che offrono. Quando lo schema per abbinare cambia, basta cambiare la regex, non l'algoritmo, o lo strumento / qualunque cosa, ed è bello e funziona di nuovo. E poiché sono una stringa magica, puoi metterla fuori dal codice sorgente, se lo desideri. E un'altra cosa che mi fa pensare al perl, se scrivi una regex lunga più di 20 caratteri, sembra che tu abbia ottenuto molto, almeno per me, è così pulito e compatto. Sono anche un programmatore pigro, non mi piace scrivere molto codice con una bella identificazione e commenti e aggiungere alcuni bug al mix.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.