Un modo migliore di fare Regex? [duplicare]

8

Non mi piacciono le espressioni regolari, ogni volta che torno ad esso mi sembra di doverlo imparare di nuovo. È anche incredibilmente difficile mantenere, modificare e capire a colpo d'occhio cosa sta facendo.

Qualcuno ha mai provato a scrivere un altro livello su di esso che trasformi in espressioni reich più semantiche? Immagino che funzioni sulla falsariga di:

AnotherString = "coffee hello beep 15"

FindString.StartsWith string longer than 5
FindString.Contains "beep" after "hello"
FindString.EndsWidth int < 20
FindString.DoesntContain "no!!" and DoesntContain "what!"
Foreach FindString match in AnotherString
    ...
Next

Questo probabilmente non è il più grande esempio di sempre, ma l'idea è che il modello sia costruito con una sorta di linguaggio semantico significativo che può scomporre in espressioni regolari tradizionali. Quanto sopra sarebbe molto più facile da modificare per uno sviluppatore. Ho una sorta di invisione che è come SQL / Linq in una certa misura.

Renderebbe l'espressione regolare molto più semantica e mantenibile. È stato provato prima, ed è una cattiva / buona idea provarlo? Potrebbe funzionare?

Modifica

Forse questo è un esempio migliore (so che gli URL sono notoriamente difficili da analizzare e questo è troppo semplificato):

string UserInputtedURL = "http://www.google.com/page.html?ID=5"

Protocols = {"http", "https"};
Domains = {"com", "net", "org"}
Rule.CaseSensitive = false;
Rule starts with Protocols OR starts with "www";
Rule followedby string endson "."
Rule followedby Domains
Rule if stringend or endswidth " " end else continuewith Ruleset2

RuleSet2.startswith "/"
etc...

if(UserInputtedURL.Matches(Rule)){
    // URL is valid!
}
    
posta Tom 12.05.2011 - 19:40
fonte

9 risposte

8

Questo è già stato fatto, almeno per Perl.

Vedi link

Non ha davvero conquistato il mondo, ma potrebbe essere un buon punto di partenza se vuoi scrivere un meccanismo simile per un'altra lingua.

Non è difficile trovare le nozioni di base su RegExes; Trovo che i dialetti di commutazione (Emacs vs Perl Compatible Regular Expressions vs quella strana variante nella finestra di dialogo di Visual Studio Find, ad esempio) il problema più grande. Non sarei motivato a imparare una versione "plain English". È quasi più facile accettare l'astrazione, perché anche la traduzione in lingua naturale dei simboli comunemente usati è imperfetta.

    
risposta data 12.05.2011 - 20:32
fonte
25

Lo scopo principale delle espressioni regolari è di fornire una notazione concisa per la formulazione di istruzioni che descrivono linguaggi regolari (IOW che corrisponde a una stringa basata su regole). Una notazione verbosa che genera una notazione così tersa è fondamentalmente un dispositivo Rube Goldberg.

Inoltre, dato quanto segue:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. — Jamie Zawinski

Sembra che tu stia facendo quanto segue:

Some people, when confronted with using regular expressions, think "I know, I'll write a language that generates regular expressions."

Ora hai tre problemi.

    
risposta data 12.05.2011 - 20:22
fonte
6

Ciò che proponi è incredibilmente prolisso. Anche se la regex può essere difficile da digerire se fatta male, e ne prende alcuni (solo un po ', direi - raramente leggo o scrivo regex, ma ricordo ancora la sintassi per le caratteristiche più importanti (ripetizione, classi di caratteri, lookahead ) e posso leggere regex usando quelle caratteristiche in modo relativamente fluente) per abituarmi, preferirei qualcosa di simile a questo che richiede di scrivere una frase pseudo-inglese per qualcosa che può essere espressa perfettamente con pochi caratteri. Considera anche la complessità (e la propensione all'errore) di un'implementazione di tale linguaggio!

Un altro problema che devo sollevare: i controlli che utilizzi come esempi includono alcune cose che sono assolutamente irragionevoli da fare con espressioni regolari - terminare con un intero è abbastanza facile, ma il confronto dei numeri è un no-go con espressioni regolari . Inoltre, molti di questi test vengono scritti più facilmente con gli strumenti di elaborazione nativa delle stringhe del linguaggio di programmazione, controllando la lunghezza, ad esempio, o la sottostringa che verifica se la stringa diventa più lunga o dinamica. Il fatto che le regex esistano e che siano utili a volte non significa che devi usarle per l'elaborazione di tutte le stringhe. Usali con cura e va tutto bene.

    
risposta data 12.05.2011 - 19:56
fonte
5

Ciò che è semplice per gli umani è infinitamente complesso per i computer:

Ciò che stai descrivendo in quasi AppleScript come nella sua sintassi, e AppleScript è universalmente detestato, anche da persone che lo conoscono bene, la sintassi può sembrare facile e leggibile, ma la sua verbosità è la sua caduta, a meno che tu non lo faccia mai giorno dimentichi tutte le regole della grammatica e delle parole chiave e diventa altrettanto opaco quanto la sintassi regex. È difficile per i principianti capire a causa della verbosità e difficile per gli esperti a causa della sua verbosità.

Il tuo esempio di uomo di paglia inventato:

Rule followedby string endson "."

Quindi come faccio a ricordare di usare followedby invece di followed by o after o before o precedes o preceding o una qualsiasi delle decine di alternative inglesi a quel concetto di "venuta dopo "qualcos'altro. Puoi applicare la stessa logica a endson che potrebbe essere endswith o endingwith o ending , dovresti comunque avere un foglio cheat o un libro per utilizzare la sintassi proposta.

    
risposta data 12.05.2011 - 20:11
fonte
3

Certo che potrebbe funzionare, ma sarebbe tremendamente difficile da implementare (imho), quando prendi in considerazione qualsiasi cosa tranne la più elementare delle espressioni.

Regex è un linguaggio tutto suo. Una volta capito come funziona, non dimenticarlo (potrebbe essere necessario un aggiornamento sulla sintassi, ma è lo stesso per tutte le lingue) e un wrapper non è più necessario (e l'overhead aggiuntivo sarebbe indesiderato).

Ho pensato (in qualche modo) come te finché non ho letto Mastering delle espressioni regolari (O'Reilly). Consiglio vivamente di prenderlo.

    
risposta data 12.05.2011 - 19:48
fonte
2

Quello che vuoi è un DSL per creare espressioni regex. Questo non è troppo difficile. Diventerà complesso / prolisso dai flag per l'acquisizione di gruppi, codici speciali per classi di caratteri usate di frequente, ancoraggio e così via.

Le basi sono:

  1. un singolo carattere è un'espressione regolare.
  2. se r è un'espressione regolare, quindi begin r end è anche un'espressione regolare.
  3. Se r1 e r2 sono regex allora r1 allora r2 è una regex
  4. Se r1 è un'espressione regolare, e n è un numero intero e m è o un numero intero o molti , quindi r1 fór n a m volte è un'espressione regolare
  5. Se r1 e r2 sono regex, quindi r1 o r2 è un'espressione regolare.

Naturalmente, si vorrebbe abbreviare:

'h' then 'e' then 'l' then 'l' then 'o'

con

"ciao"

Allo stesso modo, dopo aver usato questo DSL per un po 'di tempo, uno vorrebbe scrivere

\s*

invece di

begin ' ' or '\t' or '\r' or '\n' end for 0 to many times

Quanto segue è interessante: potrebbe esserci un universo parallelo che è esattamente come il nostro, tranne che sono state introdotte espressioni regolari ed erano comuni in un DSL prolisso come sopra. E nello stackexchange.com di questo universo, una persona potrebbe chiedere perché le espressioni regolari devono essere così goffe? Ha avuto una buona idea di rendere il lavoro con le espressioni regolari molto più semplice inventando una notazione concisa ma ugualmente potente ....

    
risposta data 12.05.2011 - 20:52
fonte
1

Un'alternativa alle espressioni regolari è Backus-Naur Form , e alcune altre varianti umane come EBNF o ABNF. Approssimativamente, ogni parte della grammatica è suddivisa in una "regola di produzione", con una definizione non terminale sulla sinistra e una sequenza di terminali e non terminali che descrive la regola sulla destra. il tuo esempio, in BNF sarebbe simile a questo:

expr ::= startword "hello" "beep" endword
       ;

startword ::= WORD_CHAR WORD_CHAR WORD_CHAR WORD_CHAR WORD_CHAR 
            | startword WORD_CHAR
            ;

endword ::= DIGIT
          | "1" DIGIT
          ;

Inoltre, BNF sembra esprimere le lingue context free , un superset appropriato dei linguaggi regolari che descrivono le espressioni regolari.

    
risposta data 02.07.2011 - 08:13
fonte
1

Il modo migliore per fare espressioni regolari è apprenderle e comprenderle, o non usarle affatto. Utilizzare qualche altro strumento come scusa per non apprendere le espressioni regolari significa che devi "apprenderli" ogni volta che li incontri.

Trascorri un giorno, solo una (piena, non distratta) giornata per studiare a fondo le espressioni regolari e sarai ricompensato con un nuovo strumento che potrai utilizzare per tutta la tua carriera. Avrai anche una comprensione molto maggiore di quando sono appropriati e, cosa più importante, quando non lo sono.

    
risposta data 17.04.2013 - 13:27
fonte