Come impari le espressioni regolari? [chiuso]

80

Non sto chiedendo a dove imparare. Ho trovato molte buone risorse online e libri ecc.

Ma come diamine li affronterò. Dov'è l'inizio, la fine? Quando il processore regexp avanza sul testo, quando mantiene il suo stand e prova un'altra corrispondenza? ecc.

Mi sento come cercare di capire i geroglifici sulle piramidi egiziane.

    
posta dumbBoy 17.04.2014 - 22:33
fonte

18 risposte

67

Penso che la conoscenza della teoria degli automi sia fondamentale per la comprensione.

Una volta capito cos'è un automa e come sono definite le lingue regolari , comprendendo il le espressioni regolari saranno molto più semplici.

Per quanto riguarda la sintassi specifica e le differenze tra le varie implementazioni ... Bene, alcune cose che devi solo ricordare. Ci sono anche aiuti anche per questo.

Modifica

Alcuni dei commenti sottostanti hanno sollevato punti importanti:

  1. Non dimenticare che le espressioni regolari (come implementate nella maggior parte dei linguaggi di programmazione) sono un superset delle espressioni regolari nella teoria degli automi. Mentre un buon background teorico è un punto di partenza utile, non ti dirà tutto. (Grazie, David Thornley)

  2. Molti commentatori affermano che è possibile imparare le varie sintassi regex senza imparare le basi teoriche. Se è vero che puoi imparare la sintassi senza comprendere appieno il modo in cui funziona, è stata la mia impressione che la piena comprensione fosse ciò che l'OP cercava. La domanda riguardava la base reale: quando il processore avanza? Quando si ferma? Come decide che è una partita? Questa è la base, questa è la teoria, ed è basata sulla teoria degli automi. Certo, puoi guidare una macchina senza sapere come funziona il motore. Ma se ti viene chiesto "in che modo il gas lo fa davvero guidare" - tu devi parlare di come è costruito il motore, vero?

risposta data 18.04.2014 - 01:26
fonte
36

Praticando.

Ho imparato divertendosi con il web scraping. Sono sicuro di non essere stato solo a farlo solo per divertimento.

Un esempio: scrivi un codice che recuperi gli ultimi risultati di calcio, tennis (lo sport che ti piacciono di fatto) dal tuo sito di sport preferito. Fatelo scrivendo del codice per caricare la pagina, estrai i punteggi con espressioni regolari e li invii alla console o ad un file di testo. Assicurati che con l'espressione regolare scelta, recuperi solo i punteggi e nient'altro. A volte questo può essere piuttosto impegnativo: -)

Secondo esempio: scrivi un codice che recuperi l'immagine del tuo webcomic preferito, (mi piace molto Sinfest per esempio) e che i negozi da qualche parte sul tuo disco fisso. Utilizza solo espressioni regolari per recuperare il tag "img" e il suo contenuto. Opzionalmente anche recuperare il titolo se è memorizzato da qualche parte.

    
risposta data 25.09.2011 - 12:18
fonte
23

So che non chiedi risorse ma Padroneggiare le espressioni regolari di Jeffrey EF Friedl è stato il modo in cui ho imparato come funzionano e come usarli. Anche dopo aver raggiunto il punto di usarne molti per analizzare cose diverse, il primo capitolo ha avuto nuove cose per me.

Vuoi capire quelle maledette espressioni regolari? Leggi questo libro.

    
risposta data 23.09.2011 - 09:41
fonte
19

Where is the start of it, the end? When does the regexp processor advance on the text, when does it hold its stand and tries another match? etc.

Vorrei iniziare chiarire i tuoi obiettivi e quindi capire il tuo stile di apprendimento .

Ciò che mi ha colpito della tua domanda è che chiedi "come imparo le espressioni regolari?" e subito dopo segui la domanda "come funziona il motore di espressioni regolari internamente?" Sembra che tu stia insinuando che queste due cose abbiano qualcosa a che fare l'una con l'altra, il che è un punto significativo. Forse sei una persona che impara come funziona qualcosa smontandola o costruendola da sola.

Per le applicazioni per principianti, di solito non è necessario capire come funziona uno strumento per poterlo utilizzare in modo efficace. Non è necessario sapere come funziona un motore di perforazione per praticare fori nel legno; devi capire come usare il trapano, non come costruire un trapano.

Quindi qual è il tuo obiettivo? Intendi imparare come creare un motore di espressioni regolari? o hai intenzione di imparare come utilizzare in modo efficace le espressioni regolari per risolvere i problemi aziendali? Raggiungere quei diversi obiettivi richiede probabilmente diverse tecniche di apprendimento.

Per rispondere alla domanda specifica su come funziona il motore delle espressioni regolari: dipende. L'approccio teorico "classico" alle espressioni regolari consiste nell'utilizzare l'espressione regolare come modello per un automa finito non deterministico, quindi costruire l'automa finito deterministico equivalente e quindi eseguire quell'automa contro l'input.

Quasi nessuno lo fa in realtà per diversi motivi. Innanzitutto, il numero di stati moltiplicato per il numero di possibili caratteri di input produce una tabella di transizione dello stato che è pazzesca anche per le piccole espressioni regolari. Certo, la maggior parte di ciò può essere compresso, ma ancora, ci sono molte regole di transizione. In secondo luogo, altri approcci sono generalmente più veloci. Terzo, le cosiddette espressioni "regolari" si trovano nelle moderne librerie regexp, niente del genere. Non sono affatto lingue regolari ; sono spesso riconosciuti dagli automi pushdown, non da linguaggi di automi finiti.

(Ho iniziato a scrivere una lunga serie su come funziona tutta questa roba, ma ho perso il controllo solo dopo primi dodici articoli . Potresti trovarli interessanti se desideri un breve riassunto sullo sfondo teorico delle espressioni regolari di base.)

I motori di espressioni regolari reali utilizzano in genere una strategia di backtracking. Il motore di espressioni regolari che abbiamo creato per il motore JScript oltre un decennio fa ora compila l'espressione regolare in un linguaggio bytecode che include le primitive per il riconoscimento delle sequenze e il backtracking agli stati precedenti. Abbiamo quindi creato un interprete per quel codice bytecode.

Non vorrei provare a capire come funziona un motore regexp prima di avere una conoscenza abbastanza solida di come usare usare le espressioni regolari. Concentrati su questo prima di iniziare a scavare nelle strategie di ottimizzazione dei vari motori.

    
risposta data 22.09.2011 - 19:06
fonte
6

How the heck do I tackle them?

Come ogni cosa nuova:

10 Study
20 Practice
30 goto 10

Studio

Trovo che gli insegnanti di maggior successo inizino a insegnare qualsiasi argomento fornendo prima un po 'di background all'argomento. È importante avere un contesto di ciò che stai imparando e, soprattutto, perché lo stai imparando.

È tutta la corrispondenza di stringhe

Le espressioni regolari sono un mezzo per abbinare i modelli nel testo. È un linguaggio dichiarativo incorporato in numerosi altri linguaggi di programmazione.

Vorrei sottolineare che è un linguaggio dichiarativo, le espressioni regolari sono utili per esprimere quale stringa da abbinare, ma non esprimono in alcun modo come il programma è quello di fare la corrispondenza. Per questo motivo è possibile utilizzare espressioni regolari molto rapidamente e molto lentamente nello stesso linguaggio di programmazione semplicemente utilizzando un parser di RegEx diverso.

Il motivo per la creazione di espressioni regolari è lo stesso per la creazione della maggior parte dei linguaggi di programmazione: i programmatori si sono trovati a svolgere sempre lo stesso compito complicato e hanno deciso di volere un modo più semplice di scrivere il codice.

Alcuni (e dovrebbero) lamentarsi della mia precedente frase dicendo qualcosa sulla falsariga di:

RegEx non semplifica il programma.

è vero

RegEx non rende più semplice un programma, RegEx rende scrivendo il programma più semplice. È ancora necessario essere accurati nei test per accertarsi che tutti i casi corretti siano corretti, e che tutti i casi errati non lo siano. È davvero difficile testare "tutti", e con schemi complicati, è davvero difficile testare "la maggior parte". Nel peggiore dei casi, dovresti comunque testare "alcuni" casi.

consente di incorporare alcuni esempi Ho scelto obbligatoriamente il motore RegEx di JavaScript perché posso verificarlo facilmente nel browser e perché non dovrò eseguire alcuna operazione di escape delle stringhe durante l'utilizzo di valori letterali RegEx.

Quando esegui la normale corrispondenza delle stringhe, prova un valore di stringa contro un altro. Possono venire da qualsiasi luogo, ma alla fine ci vogliono due stringhe confrontandole l'una con l'altra:

if ( 'foo' == 'bar' ) doSomething();

Questo esempio fa schifo perché non farà mai fare nulla

if ( foo == 'bar' ) doSomething();

Molto meglio; ora, in realtà non sappiamo in anticipo se qualcosa sarà fatto o meno. Ora possiamo iniziare ad accettare l'input dell'utente:

if ( prompt( 'Say "bar" to do something.' ) == 'bar' ) doSomething();

Meraviglioso, ora gli utenti possono inserire bar e qualcosa succederà, finché non riceverai segnalazioni di bug da parte degli utenti che dicono che "bar" non funziona, o che "BAR" non funziona o che hanno digitato BRA 100 volte e non succede mai niente.

Ignorando gli errori ortografici e i caratteri extra, 'bar' != 'BAR' , e i programmatori devono pensare a un modo per verificare dove i caratteri sono nel caso sbagliato.

Soluzione semplice, usa toLowerCase . Funziona in modo meraviglioso, ma che ne è dei nostri utenti che utilizzano l'inglese britannico rispetto all'inglese americano quando stai abbinando something == 'color' ? Ora dovrai abbinare something == 'color' || somthing == 'colour' .

Per farla breve, gli schemi semplici si trasformano in molto codice ripetitivo molto rapidamente.

L'esempio di colore può semplicemente essere abbinato a:

/colou?r/.test( something )

Una solida conoscenza delle basi delle espressioni regolari può ridurre in modo significativo la quantità di tempo che rifiuti di reinventare la ruota.

Dove studiare

La maggior parte delle lingue che implementano espressioni regolari ha almeno una risorsa disponibile per la sintassi specifica dell'uso di espressioni regolari all'interno di quella lingua. Uno per JavaScript può essere trovato su MDN

leggi.
tutto.
quindi rileggilo.

Ci vuole tempo per imparare, pensarlo come un investimento: un'ora per imparare RegEx ora risparmia un'ora la prossima volta che devi fare un po 'di corrispondenza con le stringhe, e poi un'altra ora la prossima volta.

Practice

Dopo aver letto tutto su RegEx, probabilmente non capirai la maggior parte di esso. Questo perché in realtà non fai qualcosa con esso.

Ho menzionato il motivo per cui ho scelto JS per questo esempio, ti esorto a confonderlo con il tuo browser. È veloce e puoi farlo direttamente nella tua barra degli URL.

JS ha alcuni modi diversi e semplici per usare RegEx:

string.match( regex )
regex.exec( string )
regex.test( string )

A partire da qualcosa di semplice come:

javascript:'color'.match(/colou?r/);

è un modo semplice per mettere piede nella porta. Gioca con esso, rompilo e vedi cosa corrisponde, e cosa no.

Quando rimani bloccato in allenamento, continua con 30 . Devi leggere per saperne di più, ma devi esercitarti per capire veramente quello che hai imparato.

    
risposta data 23.09.2011 - 03:36
fonte
5

Brian Kernighan scrive un semplice processore reg-ex nel libro Beautiful Code . Mi rendo conto che non stai cercando risorse, ma potrebbe essere utile vedere un'implementazione di base, all'interno.

    
risposta data 22.09.2011 - 13:30
fonte
4

Nel normale sviluppo, il codice di debug può fornire informazioni molto utili. Le espressioni regolari non sono diverse. Quindi, a rischio di sembrare un annuncio, prendi RegexBuddy . Ha un ottimo strumento per visualizzare visivamente ciò che il motore sta facendo mentre gestisce la tua espressione e la stringa di input.

    
risposta data 22.09.2011 - 19:23
fonte
3

Le espressioni regolari possono diventare molto complicate molto rapidamente, quindi ti consiglio di iniziare a impararlo usando i tutorial. Sappi che la forma più semplice di espressione regolare è una stringa che rappresenta ciò che stai cercando. Sfortunatamente, per essere in grado di definire regole di ricerca speciali, richiede determinati caratteri e questi caratteri devono essere preceduti da escape o si creerebbe un'espressione regolare non valida o errata.

Il mio consiglio è di iniziare con un esempio di qualcosa che stai cercando e di evaderlo. Quindi, in altre parole, se stavi cercando qualcosa tra parentesi, prendi un esempio di una di queste stringhe nel testo che stai cercando: (this is an example of something you'd want to find)

Inizia eseguendo l'escape dei caratteri in modo da cercare il carattere letterale: \(this is an example of something you'd want to find\)

Provalo, verifica che trovi il tuo esempio correttamente. Quindi generalizza l'espressione per trovare qualsiasi testo di questo tipo, non solo l'esempio trovato. Quindi diventerebbe quindi: \([^)]*\) (indica qualsiasi carattere che non è ")" per qualsiasi numero di occorrenze, incluso 0).

Provalo di nuovo e verifica che non trovi solo il tuo esempio, ma altri lo apprezzino. Cerca espressioni regolari più complicate ma più frequenti su Internet e applicale alle espressioni regolari esistenti per evitare di doversi preoccupare di ogni singola possibilità.

Questo è tutto. E oh, impara e ama \ Q ... \ E. Nella maggior parte dei linguaggi di espressioni regolari, \ Q indica l'inizio di un modello letterale e \ E segna la fine, nel caso in cui devi affrontare la ricerca di modelli particolarmente sofisticati e non sapere come sfuggirli. Questo mi ha salvato la vita più di un paio di volte.

    
risposta data 22.09.2011 - 12:31
fonte
3

Ti darò una risposta semplice per una semplice domanda. In primo luogo, è necessario capire quali sono le espressioni regolari (RegEx): cosa fanno, a cosa servono. Quindi, un ottimo strumento per iniziare.

  1. Che cos'è? RegEx è un linguaggio per esprimere la corrispondenza dei modelli. Vale a dire, utilizzandolo, è possibile creare una combinazione di caratteri che riconosce o trova pattern nel testo. Come è utile? Nella programmazione, puoi dire ai computer di far corrispondere il testo da qualche fonte (un input dell'utente, una pagina web, ecc.) E scoprire se all'interno di esso sono contenuti specifici pattern di testo. Ad esempio, un punto (.) Rappresenta qualsiasi carattere - lettera o numero. I numeri nelle parentesi rappresentano numeri di iterazioni, quindi ". {1,30}" indica qualsiasi carattere, ripetuto tra 1 e 30 volte - in altre parole, non puoi avere una stringa vuota e non può essere più lungo di 30 personaggi. E va avanti da lì.

  2. Come iniziare ad imparare? Lo strumento migliore in assoluto che ho visto è Expresso , ma è solo per Windows. Ha una GUI molto ampia in cui si fa clic sugli elementi che si desidera aggiungere all'espressione, quindi un tester per verificarlo rispetto a vari input per vedere i risultati. Non ho visto nulla di buono su Mac (ma sto usando Windows su VMWare, quindi non ho davvero bisogno di una versione per Mac), non ho passato molto tempo a cercare su Linux.

risposta data 22.09.2011 - 20:24
fonte
3

Oltre a un buon riferimento, il modo in cui impari è di utilizzare strumenti di apprendimento di qualità. Uno utilizza l'editor Vim open-source, con due opzioni:

  1. : imposta incsearch ... mentre digiti in un pattern di ricerca sulla riga di comando, l'editor al volo salta al primo pezzo di testo che corrisponde ed evidenzia esattamente ciò che corrisponde. Se digiti qualcosa che non corrisponde più a nulla, Vim riporta il cursore al punto in cui ti trovavi quando hai iniziato.
  2. : imposta hlsearch ... questo dice a Vim di mostrare uno sfondo evidenziato su tutto il testo che corrisponde alla ricerca RE corrente.

L'altro è usare una chiamata di strumento gratuito RegExCoach . Si incolla nel testo che si desidera cercare, quindi in un'altra finestra si sviluppa la propria espressione regolare. Come Vim, mette in evidenza le partite di successo al volo.

    
risposta data 22.09.2011 - 20:59
fonte
2

Si inizia con un confronto di stringhe di base. Molto facile, ma anche non così potente.

In seguito, potrebbe esserti verificato che hai bisogno di confronti caso-insensitive, in modo che "greco" e "GreeK" siano uguali. Questo è un po 'più potente.

Un giorno noti piccole differenze nell'ortografia non dovrebbe impedire a 2 parole di paragonare uguali: cioè "organizzare" e "organizzare" dovrebbe essere uguale. Ti siedi e scrivi del codice che fa questo e sei felice.

Finché non ti astragga un po 'di più e ti rendi conto che a volte desideri che tutte le parole che terminano in "ize" siano paragonabili ai loro fratelli nell'ortografia britannica. Oppure, ripetizioni di alcuni archi una certa quantità di volte. E, naturalmente, hai bisogno di combinare tutto questo.

E così via. Infine, molto probabilmente finirai con qualche notazione in cui non tutti i personaggi rappresentano se stessi. Nient'altro è una regexp. Si può vederlo come descrizione di un insieme di stringhe.

E quindi, è abbastanza semplice e si basa sui seguenti 3 principi di base:

Hai delle espressioni regolari di base: caratteri che stanno per se stessi, classi di caratteri, abbreviazioni pratiche e poco pratici per classi di caratteri come \ d o \ p {Lu} per lettere maiuscole.

E poi, hai alcune possibilità di combinarli: se r1 e r2 sono espressioni regolari, allora lo sono anche r1r2 r1 | r2 (r1).

Ultimo, ma non meno importante, i modificatori di ripetizione: r? r * r + r {n, m}

Questa è la maggior parte che devi sapere. Qualsiasi altra cosa puoi cercare quando ne hai bisogno.

    
risposta data 22.09.2011 - 13:17
fonte
2

Due buone altre risposte ti dicono di apprendere la teoria dietro le espressioni regolari e di esercitarti, che sono entrambi ottimi consigli. Ti suggerisco anche di prendere un buon strumento di regex visivo per aiutarti se sei serio.

RegexBuddy , ad esempio, ha una modalità di debug visuale che ti consente di passare all'esecuzione di un'espressione regolare e ti mostra tramite evidenziazioni e testo esplicativo cosa sta facendo il motore regex in ogni fase. C'è un video che mostra questo debug sul loro sito.

    
risposta data 22.09.2011 - 19:03
fonte
2

Tutto ciò che possiamo darti è più risorse da imparare. Questa domanda è di per sé una risorsa.

A proposito, ho imparato abbastanza facilmente le espressioni regolari da questo sito: link

    
risposta data 22.09.2011 - 21:40
fonte
1

Per me, vedere che cosa fa l'espressione regolare, mentre lo sto creando, mi aiuta davvero a semplificarmi la vita e mi ha aiutato a capirli meglio.

Per fare questo, aprirò un file con il testo di destinazione in Emacs, e quindi userò il comando isearch-forward-regexp . Quando immetti l'espressione regolare, Emacs ti mostra ciò che corrisponde (è la parte "isearch").

Per eseguire il comando, in Emacs, puoi utilizzare <ESC>xisearch-forward-regexp .

    
risposta data 22.09.2011 - 22:38
fonte
1

Ho imparato le espressioni regolari imparando flex e bisonti, che sono usati per costruire analizzatori e parser lessicali. Non si poteva avere un parser senza espressioni regolari, e il libro lexx e yacc è incredibilmente bravo a camminare attraverso teoria senza muoversi troppo velocemente.

Fondamentalmente, praticamente tutti i motori regex in questi giorni seguono gli stessi principi. Sono tutte macchine a stati finiti e se ne hai davvero voglia, allora hai un vantaggio su quasi tutti i codici che scrivi. È simile all'apprendimento della ricorsione in quanto, una volta ottenuto, lo si applica ai problemi istintivamente. Sono facili da risolvere con lo strumento giusto, ma molto difficile senza.

Un'altra cosa sull'apprendimento di lexx e yacc, rispetto alle espressioni regolari, è che impari come lavorano internamente. Come il programma guarda avanti, perché termina una partita, come tiene i dati e molto altro ancora. Comprendere i puntatori è un must assoluto, ma se ottieni lexx e yacc, e lo analizzi dall'inizio imparerai tutto ciò che hai chiesto e avrai uno strumento estremamente potente per il resto della tua carriera.

Questa domanda include un sacco di risorse per l'apprendimento e uno scheletro flessibile che ho gettato insieme.

    
risposta data 23.05.2017 - 14:40
fonte
1

Più, prima cerco di verificare che non ci sia un modo più semplice per risolvere il problema / "tokenize" la stringa.

Quando non riesci a trovarne uno, considero il problema come un problema non nel cercare di far corrispondere ciò che vuoi fuori dalla stringa, piuttosto si tratta di NON corrispondere a ciò che non vuoi. Questo è principalmente perché le regex sono avide. Ma mi è servito bene come approccio per ottenere ciò che voglio.

Ecco un esempio:

string = "Sep 22 19:57:38 host fcron[9137]: \
          Job fbsetbg -r $HOME/backgrounds/ \
          started for user user (pid 9138)"

per abbinare il minuto:

string.match /^\w+\s\d+\s\d+:(\d+):\d+\s\w+\s/ # correct but bad
string.match /\d+:([^:]+):\d+/                 # correct and good

Invece di cercare di trovare il tempo insieme a tutto il resto, prova a trovare i confini distinti.

L'esempio è un po 'forzato, ma tutto ciò che potrei inventare.

    
risposta data 23.09.2011 - 05:18
fonte
1

Un approccio che ho usato è stato trovare una serie di progetti open source che necessitavano di aggiornamenti di sintassi e quindi scrivere uno script sed sempre più complesso, che comprendeva molte espressioni regolari.

Lo script doveva essere eseguito su molti file diversi in ogni progetto open source. Quindi esegui molti progetti diversi con stili diversi. Ho iniziato con qualcosa di molto semplice come %s/before/after , quindi ho scoperto che corrispondeva a troppi casi. quindi ho aggiunto più cose per impedirlo. Poi ho trovato diversi progetti utilizzando diversi stili di sintassi che richiedevano modifiche diverse.

Alla fine ho finito con

  • grandi capacità e conoscenze sulle espressioni regolari
  • buone capacità con sed
  • aiutare molti progetti open source
  • ottenere molte attività di contribuzione mostrate sul mio profilo github
  • un altro ottimo strumento "swiss-army knife" per la cinturone virtuale

ed è stato aiutato in questo approccio dalla necessità di

  • raggiungere obiettivi reali senza barare
  • usa le abilità (regex) come parte di un obiettivo più grande con maggiore motivazione.
  • essere in grado di mostrare la prova delle competenze che ho imparato modificando il codice degli altri e verificando le modifiche.

Inoltre passerò oltre che ci sono un sacco di siti per le varie lingue - ruby, javascript, ecc. che ti permetteranno di giocare con espressioni e testo di esempio per una gratificazione immediata. Questi sono:

regex in più lingue su un sito

  • link javascript / php / python
  • link PHP / JAVA / JS / ASP / .NET / C # / VB.NET

concentrati sui gruppi di incontri:

risposta data 18.04.2014 - 01:28
fonte
0

Ho trovato l'apprendimento di espressioni regolari simili all'apprendimento delle tabelle di moltiplicazione - sì, è necessario capire le idee che stanno dietro, ma alla fine, devi farlo spesso e ripetutamente.

Quando stavo imparando, mi proponevo l'obiettivo di fare alcuni esercizi di regex al giorno. In pratica, questo significava almeno una volta al giorno, provavo a guardare una stringa o un testo sul mio schermo, e mi inventavo una sfida: "posso ottenere tutti gli indirizzi e-mail da qui" o "trova tutto occorrenze della parola 'codice' usata come un verbo piuttosto che come un nome, "cose del genere.

Il fatto che per alcune settimane sia stato davvero proficuo - e ovviamente sono necessarie revisioni periodiche e rinfreschi. Ne ho bisogno per uno.

Ho trovato utile anche questo strumento online, in quanto consente di testare la regex in tempo reale: link

    
risposta data 23.09.2011 - 03:09
fonte

Leggi altre domande sui tag