Conosci i tuoi sapori regex
C'è una quantità sorprendente di persone che pensano che le espressioni regolari siano essenzialmente agnostiche del linguaggio. Tuttavia, in realtà ci sono differenze abbastanza sostanziali tra i sapori, e soprattutto per il golf del codice è bene conoscerne alcuni e le loro caratteristiche interessanti, in modo da poter scegliere il meglio per ogni attività. Ecco una panoramica di diversi sapori importanti e ciò che li distingue dagli altri. (Questo elenco non può davvero essere completo, ma fammi sapere se mi sono perso qualcosa di veramente evidente.)
Perl e PCRE
Li sto lanciando in un singolo piatto, poiché non ho troppa familiarità con il sapore Perl e sono per lo più equivalenti (dopotutto PCRE è per le espressioni regolari compatibili con Perl). Il vantaggio principale del sapore Perl è che puoi effettivamente chiamare il codice Perl dall'interno della regex e della sostituzione.
- Ricorsione / subroutine . Probabilmente la caratteristica più importante per il golf (che esiste solo in un paio di gusti).
- Modelli condizionali
(?(group)yes|no).
- Sostiene il cambiamento del caso nella stringa di sostituzione con
\l, \u, \Le \U.
- PCRE consente l'alternanza in lookbehinds, dove ogni alternativa può avere una lunghezza diversa (ma fissa). (La maggior parte dei gusti, incluso il Perl, richiede che i lookbehind abbiano una lunghezza fissa complessiva.)
\G per ancorare una partita alla fine della partita precedente.
\K per resettare l'inizio della partita
- PCRE supporta sia le proprietà dei caratteri Unicode che gli script .
\Q...\Eper sfuggire a serie più lunghe di personaggi. Utile quando stai cercando di abbinare una stringa che contiene molti meta-caratteri.
.NETTO
Questo è probabilmente il sapore più potente, con solo poche carenze.
Una lacuna importante in termini di golf è che non supporta quantificatori possessivi come altri sapori. Invece di .?+dover scrivere (?>.?).
Giava
- A causa di un bug (vedi Appendice) Java supporta un tipo limitato di lookbehind di lunghezza variabile: puoi guardare indietro fino all'inizio della stringa con
.*da dove puoi ora avviare un lookahead, come (?<=(?=lookahead).*).
- Supporta l'unione e l'intersezione delle classi di caratteri.
- Ha il supporto più esteso per Unicode, con classi di caratteri per "Script Unicode, blocchi, categorie e proprietà binarie" .
\Q...\E come in Perl / PCRE.
Rubino
Nelle versioni recenti, questo sapore è altrettanto potente di PCRE, incluso il supporto per le chiamate di subroutine. Come Java, supporta anche l'unione e l'intersezione delle classi di caratteri. Una caratteristica speciale è la classe di caratteri integrata per le cifre esadecimali: \h(e negata \H).
La caratteristica più utile per giocare a golf è come Ruby gestisce i quantificatori. In particolare, è possibile nidificare i quantificatori senza parentesi. .{5,7}+funziona e così fa .{3}?. Inoltre, a differenza della maggior parte degli altri sapori, se il limite inferiore di un quantificatore è 0che può essere omesso, ad esempio .{,5}è equivalente a .{0,5}.
Per quanto riguarda le subroutine, la principale differenza tra le subroutine PCRE e le subroutine di Ruby è che la sintassi di Ruby è un byte più lunga (?n)rispetto a \g<n>, ma le subroutine di Ruby possono essere utilizzate per l'acquisizione, mentre PCRE ripristina le acquisizioni al termine di una subroutine.
Infine, Ruby ha una semantica diversa per i modificatori relativi alla linea rispetto alla maggior parte degli altri sapori. Il modificatore che di solito viene chiamato min altri gusti è sempre attivo in Ruby. Quindi ^e $abbina sempre l'inizio e la fine di una riga, non solo l'inizio e la fine della stringa. Questo può farti risparmiare un byte se hai bisogno di questo comportamento, ma ti costerà byte extra se non lo fai, perché dovrai sostituire ^e $con \Ae \z, rispettivamente. In aggiunta a ciò, il modificatore che di solito viene chiamato s(che fa .corrispondere gli avanzamenti di riga) viene invece chiamato min Ruby. Ciò non influisce sul conteggio dei byte, ma deve essere tenuto presente per evitare confusione.
Pitone
Python ha un sapore solido, ma non sono a conoscenza di funzioni particolarmente utili che non troverai da nessun'altra parte.
Tuttavia , esiste un sapore alternativo che è destinato a sostituire il remodulo ad un certo punto e che contiene molte caratteristiche interessanti. Oltre ad aggiungere il supporto per la ricorsione, i lookbehinds di lunghezza variabile e gli operatori di combinazione di classi di caratteri, ha anche la caratteristica unica della corrispondenza fuzzy . In sostanza è possibile specificare un numero di errori (inserimenti, eliminazioni, sostituzioni) consentiti e il motore fornirà anche corrispondenze approssimative.
ECMAScript
Il sapore di ECMAScript è molto limitato e quindi raramente molto utile per giocare a golf. L'unica cosa che sta succedendo è che la classe di caratteri vuota negata si [^] abbina a qualsiasi personaggio così come la classe di caratteri vuota che fallisce incondizionatamente [](al contrario del solito (?!)). Sfortunatamente, il sapore non ha alcuna caratteristica che lo rende utile per i normali problemi.
Lua
Lua ha il suo sapore abbastanza unico, che è piuttosto limitato (ad esempio non puoi nemmeno quantificare i gruppi) ma presenta una manciata di funzioni utili e interessanti.
- Ha un gran numero di abbreviazioni per le classi di caratteri integrate , tra cui punteggiatura, caratteri maiuscoli / minuscoli e cifre esadecimali.
- Con
%besso supporta una sintassi molto compatta per abbinare stringhe bilanciate. Ad esempio %b()abbina a (e quindi tutto fino a un abbinamento )(saltando correttamente coppie accoppiate interne). (e )può contenere due caratteri qui.
Incremento
Il sapore regex di Boost è essenzialmente quello di Perl. Tuttavia, ha alcune nuove e interessanti funzionalità per la sostituzione di regex, tra cui cambiamenti di caso e condizioni . Quest'ultimo è unico per Boost per quanto ne so.