May 12 2011
Regular Expression per gli intervalli numerici
Molte persone col tempo dimenticano che le espressioni regolari, comprese quelle che si usano dentro a Google Analytics, funzionano per i caratteri, e non per i numeri. Anzi, per dirla meglio, i numeri vengono trattati come caratteri invece che come cifre.
Per questo quando diciamo che l’espressione regolare [0-9] identifica “tutti i numeri da 0 a 9” diciamo una verità e ne sottindendiamo un’altra: essa identifica SOLO i numeri da 0 a 9. Per cui se voglio fare una espressione regolare che prenda da 0 a 39 non posso scrivere [0-39]. Se scrivessi così intenderei qualcosa che intercetta solo numeri di due cifre, la prima delle quali può essere 0, 1, 2 oppure 3 e la seconda delle quali è sicuramente (e solamente) un 9 un numero di una sola cifra, 0, 1, 2, 3 oppure 9 (tnx to Enrico Altavilla per la correzione).
La regular expression per intercettare tutti i numeri da 0 a 39 è un’altra:
[0-3]?[0-9]
^[0-9]$|^[1-3][0-9]$
(o un numero singolo da 0 a 9 oppure un numero di due cifre la cui prima può essere 1, 2 o 3 e la seconda può andare da 0 a 9).
Le cose si complicano ancora di più quando le cifre non sono “tonde” (chiamo tondo il 39 perché comunque si vuole intercettare tutta la decina dei trenta ed escludere dai quaranta in poi), ad esempio se si vuole fare il match da 0 a 33. La regex diventa
^([0-9]|[1-2][0-9]|3[0-3])$
praticamente la scomposizione dei numeri: “da 0 a 9, oppure da 10 a 29, oppure da 30 a 33”. Un po’ verboso, ma funziona così 🙂
Piccola precisazione quando scrivi:
> [0-39]. Se scrivessi così intenderei qualcosa che intercetta solo numeri di due cifre, la prima delle quali può essere 0, 1, 2 oppure 3 e la seconda delle quali è sicuramente (e solamente) un 9.
In realtà l’espressione [0-39] descrive un numero di una sola cifra tra “0”, “1”, “2”, “3” e “9”.
(sì, sono un rompiballe nerd…)
sei un rompiballe ma hai indubbiamente ragione 🙂 Non so che casino ho fatto con RegexDesigner ma avevo testato i mie casi e matchava. Cmq correggo. Ti devo una (SEO)birra 🙂
Non sono molto esperto in espressioni regolari, ma credo che non vada bene nemmeno l’espressione:
[0-3]?[0-9]
perché il simbolo ‘?’ cerca una corrispondenza con un carattere compreso tra 0 e 3 ma l’espressione è soddisfatta ANCHE SE NON TROVA nulla nella prima posizione (‘?’ infatti, cerca ZERO o 1 corrispondenza, quindi anche se non trova il carattere l’espressione è soddisfatta). L’espressione [0-9] invece è soddisfatta quando trova un qualsiasi carattere compreso tra 0 e 9 nella prima e nella seconda posizione. Quindi ipotizzando come input ’40’ ad esempio, 4 non trova corrispondenza con [0-3] ma ‘?’ è SODDISFATTO comunque, anche se non trova corrispondenze. ‘4’ e ‘0’ trovano corrispondenza con l’espressione [0-9]. Quindi, ipotizzando una stringa in input come “40”, quell’espressione trova ben 2 corrispondenze. Perciò non va bene. Insomma, non so se mi sono spiegato (dubito) ma credo che per verificare la corrispondenza esatta con una stringa che contenga solo una sequenza di numeri compresi tra 0 e 39, sia meglio usare un’espressione come questa:
^[0-9]$|^[1-3][0-9]$
cioè:
occorre fare un distinguo tra strighe lunghe 1 carattere e stringhe lunghe 2 caratteri. Quindi, nel caso di stringhe lunghe 1 carattere, il primo carattere deve obbligatoriamente iniziare e terminare con una sola cifra compresa tra 0 e 9, e possiamo verificarlo con l’espressione ^[0-9]$. OPPURE, se stiamo parlando di una stringa di 2 caratteri, diciamo che la stringa deve iniziare obbligatoriamente con una cifra compresa tra 1 e 3 e terminare con una cifra compresa tra 0 e 9 (verificato con l’espressione ^[1-3][0-9]$). Si può testarne l’esattezza con alcuni servizi online, tipo questo (quasi in fondo alla pagina):
http://www.zytrax.com/tech/web/regex.htm
io online di solito uso http://regexpal.com/ mentre come detto sopra sul desktop ho RegexDesigner: siccome hai ragione tu, a questo punto temo di non aver fatto casino con le regex, ma peggio ancora con i settaggi, perché al momento i risultati sono sballati (mentre regexpal conferma quanto dici)
scusate ma tutti i numeri da 0 a 39 non si ottengono semplicemente con
[0-3][0-9]
o per essere più pignoli con
[0-9]|[1-3][0-9]
La prima non prende i numeri di una cifra sola, tipo 3.
La seconda intercetta anche 41 e tutto il resto…
Ciao ho trovato l’articolo esemplificativo e molto chiaro ma mi sorge una domanda ulteriore (o una complicazione ulteriore, dipende dai punti di vista):
se volessi applicare il controllo ad un numero in una stringa più ampia (tipo una data 31-12-2087) anziché utilizzare i tag di inizio e fine stringa, è possibile usare un separatore arbitrario (nel mio esempio un -) per dividere i valori numerici da esaminare?
si, potresti dire – in italiano – “due numeri preceduti e seguiti da -” (intendendo il mese). quindi \-\d\d\- (o \-\d{2}\- )
Buongiorno,
sono alle prime armi con regex e dovrei fare convertire
es. 15/18′ in 15-18 mins.
Ho provato \d\d\/\d\d\’ replace con\d\d\-\d\d\ mins;
[0-9]+/[0-9]’ replace con[0-9]+-[0-9] mins e svariate altre opzioni di \d e [0-9]… mi cambia” /” in “-” e “‘” min “mins” ma niente da fare con i numeri….
Potreste aiutarmi?
Grazie
Ciao, non ho capito se stai parlando di GA o no. Per le sostituzioni servono le backreference.
Se vai qui https://regex101.com/ e testi
(\d\d)\/(\d\d)\’
sostituendo con
\1-\2 mins
hai quel che cerchi.
su GA le backreference sono tipo $A1 (la prima che incontra nel campo A), $B2 ( la seconda del campo B) e così via…