Double Commander utilizza la libreria gratuita TRegExpr scritta da Andrey Sorokin.
La maggior parte delle spiegazioni proviene dal file di aiuto di tale libreria.
Le espressioni regolari rappresentano un metodo ampiamente utilizzato per definire schemi di ricerca testuale. Caratteri speciali (denominati metacaratteri) consentono di specificare, ad esempio, che una determinata stringa cercata debba apparire all'inizio o alla fine di una riga, o che debba contenere n occorrenze di un carattere o gruppo di caratteri.
Double Commander supporta le espressioni regolari nelle seguenti funzionalità:
La libreria TRegExpr supporta due modalità operative: ANSI e Unicode. Durante la ricerca all'interno dei file di testo, Double Commander le utilizza entrambe (in base alla codifica del file). Durante la ricerca per nome dei file, viene utilizzata la codifica Unicode.
Qualsiasi singolo carattere corrisponde a se stesso, a meno che non si tratti di un metacarattere con un significato speciale descritto di seguito.
Una sequenza di caratteri corrisponde alla stessa sequenza nella stringa di destinazione, pertanto il criterio bluh corrisponderà a bluh nella stringa target.
Possiamo far sì che i metacaratteri o le sequenze di escape vengano interpretati alla lettera facendoli precedere da una barra rovesciata \: ad esempio, il metacarattere ^ corrisponde all'inizio della riga, ma \^ corrisponde al carattere letterale ^, \\ corrisponde a \, e così via.
Ecco alcuni esempi:
| Esempi di corrispondenza semplice | |
|---|---|
| Espressione | Risultato |
foobar |
Corrisponde alla stringa foobar |
\^FooBarPtr |
Corrisponde a ^FooBarPtr |
I caratteri possono essere specificati utilizzando una sintassi per le sequenze di escape analoga a quella impiegata in C e Perl: \n corrisponde a un carattere di nuova riga, \t corrisponde a una tabulazione, ecc.
Più in generale, \xnn, dove nn è una sequenza di cifre esadecimali, corrisponde al carattere con valore ASCII nn.
Se si necessita di codici di caratteri estesi (Unicode), è possibile utilizzare \x{nnnn}, dove nnnn rappresenta una o più cifre esadecimali.
| Sequenze di escape | |
|---|---|
| Espressione | Risultato |
\xnn |
Carattere con codice ASCII nn |
\x{nnnn} |
Carattere con codice ASCII nnnn (un byte per il testo normale, due byte per Unicode) |
\t |
Tabulazione (HT/TAB), equivalente a \x09 |
\n |
Nuova riga (NL/LF), equivalente a \x0a |
\r |
Ritorno a capo (CR), equivalente a \x0d |
\f |
Avanzamento pagina (FF), equivalente a \x0c |
\a |
Avviso (segnale acustico) (BEL), equivalente a \x07 |
\e |
Escape (ESC), equivalente a \x1b |
Ecco alcuni esempi:
| Esempi di sequenze di escape | |
|---|---|
| Espressione | Risultato |
foo\x20bar |
Corrisponde a foo bar (si noti lo spazio al centro) |
\tfoobar |
Corrisponde a foobar preceduto da una tabulazione |
È possibile specificare una classe di caratteri racchiudendo l'elenco dei caratteri tra parentesi quadre []; questo consentirà di far corrispondere a tale elemento qualsiasi singolo carattere presente nell'elenco.
Se il primo carattere dopo [ è ^, allora la classe corrisponderà a qualsiasi carattere non presente nell'elenco.
All'interno dell'elenco, il carattere - viene utilizzato per definire un intervallo: ad esempio, a-z indica tutti i caratteri compresi tra a e z, estremi inclusi.
Se si desidera includere il carattere - letterale nella classe, è necessario posizionarlo all'inizio o alla fine dell'elenco, oppure farlo precedere da una barra rovesciata.
Se si desidera includere il carattere ], è possibile posizionarlo all'inizio dell'elenco o farlo precedere da una barra rovesciata.
| Classi di caratteri | |
|---|---|
| Espressione | Risultato |
[-az] |
Corrisponde a a, z e - |
[az-] |
Corrisponde a a, z e - |
[a\-z] |
Corrisponde a a, z e - |
[a-z] |
Corrisponde a una qualsiasi delle 26 lettere minuscole da a a z |
[\n-\x0D] |
Corrisponde a qualsiasi carattere compreso tra \x0a, \x0b, \x0c, \x0d |
[\d-t] |
Corrisponde a qualsiasi cifra numerica, - o t |
[]-a] |
Corrisponde a qualsiasi carattere compreso tra ] e a |
Ecco alcuni esempi:
| Esempi di classi di caratteri | |
|---|---|
| Espressione | Risultato |
foob[aeiou]r |
Trova stringhe come foobar, foober, ecc., ma non foobbr, foobcr, ecc. |
foob[^aeiou]r |
Trova stringhe come foobbr, foobcr, ecc., ma non foobar, foober, ecc. |
I metacaratteri rappresentano l'essenza delle espressioni regolari e sono caratteri speciali.
Esistono diverse tipologie di metacaratteri, descritte di seguito.
Alcune espressioni aiutano a rilevare i separatori di riga.
| Separatori di riga | |
|---|---|
| Espressione | Risultato |
^ |
Inizio della riga |
$ |
Fine della riga |
\A |
Inizio del testo |
\Z |
Fine del testo |
. |
Qualsiasi carattere all'interno della riga |
Ecco alcuni esempi:
| Esempi di separatori di riga | |
|---|---|
| Espressione | Risultato |
^foobar |
Corrisponde solo se la stringa foobar si trova all'inizio della riga |
foobar$ |
Corrisponde solo se la stringa foobar si trova alla fine della riga |
^foobar$ |
Corrisponde solo se la stringa foobar è l'unica stringa presente all'interno della riga |
foob.r |
Corrisponde a stringhe come foobar, foobbr, foob1r, ecc. |
Per impostazione predefinita, il metacarattere ^ corrisponde esclusivamente all'inizio della stringa/testo di input, mentre il metacarattere $ corrisponde esclusivamente alla fine. I separatori di riga incorporati all'interno della stringa non corrispondono a ^ o $.
Tuttavia, si potrebbe desiderare di trattare la stringa come un buffer multilinea: in questo caso, ^ corrisponderà dopo qualsiasi separatore di riga all'interno della stringa e $ corrisponderà prima di qualsiasi separatore di riga. È possibile ottenere questo comportamento attivando il modificatore m.
\A e \Z si comportano in modo analogo a ^ e $, ma quando si utilizza il modificatore m essi non effettueranno corrispondenze multiple, a differenza di ^ e $ che invece corrisponderanno a ciascun separatore di riga interno.
Per impostazione predefinita, il metacarattere . corrisponde a qualsiasi carattere, ma se si disattiva il modificatore s, allora . non corrisponderà ai separatori di riga incorporati.
TRegExpr gestisce i separatori di riga in conformità con lo standard tecnico Unicode (Technical Standard #18):
^ corrisponde all'inizio della stringa di input e, se il modificatore m è attivo, anche dopo qualsiasi occorrenza di \x0D\x0A, \x0A o \x0D (in Unicode supporta anche: \x2028, \x2029, \x0B, \x0C o \x85). Si noti che non viene rilevata alcuna riga vuota all'interno della sequenza \x0D\x0A.
$ corrisponde alla fine della stringa di input e, se il modificatore m è attivo, anche prima di qualsiasi occorrenza di \x0D\x0A, \x0A o \x0D (in Unicode supporta anche: \x2028, \x2029, \x0B, \x0C o \x85). Si noti che non viene rilevata alcuna riga vuota all'interno della sequenza \x0D\x0A.
. corrisponde a qualsiasi carattere, ma se si disattiva il modificatore s, allora . non corrisponderà a \x0D\x0A, \x0A e \x0D (in Unicode non corrisponde nemmeno a: \x2028, \x2029, \x0B, \x0C o \x85).
Si noti che la formula ^.*$ (criterio per riga vuota) non corrisponderà a una stringa vuota all'interno della sequenza \x0D\x0A, ma vi corrisponderà nella sequenza \x0A\x0D.
Alcune espressioni aiutano a rilevare specifici gruppi di caratteri.
| Classi predefinite | |
|---|---|
| Espressione | Risultato |
\w |
Carattere alfanumerico (incluso _), equivalente a [0-9A-Za-z_] |
\W |
Carattere non alfanumerico |
\d |
Carattere numerico (cifra) |
\D |
Carattere non numerico |
\s |
Qualsiasi carattere di spaziatura (equivalente a [ \t\n\r\f]) |
\S |
Carattere non di spaziatura |
È possibile utilizzare \w, \d e \s all'interno di classi di caratteri personalizzate.
Ecco alcuni esempi:
| Esempi di classi predefinite | |
|---|---|
| Espressione | Risultato |
foob\dr |
Corrisponde a stringhe come foob1r, foob6r, ecc., ma non a foobar, foobbr, ecc. |
foob[\w\s]r |
Corrisponde a stringhe come foobar, foob r, foobbr, ecc., ma non a foob=r, ecc. |
Un confine di parola (\b) rappresenta la posizione compresa tra due caratteri in cui uno è di tipo \w e l'altro è di tipo \W (in qualsiasi ordine), considerando l'inizio e la fine immaginari della stringa come caratteri corrispondenti a \W.
| Confini delle parole | |
|---|---|
| Espressione | Risultato |
\b |
Corrisponde a un confine di parola |
\B |
Corrisponde a un non confine di parola |
Qualsiasi elemento all'interno di un'espressione regolare può essere seguito da un altro tipo di metacarattere: l'iteratore.
Utilizzando questi metacaratteri, è possibile specificare il numero di occorrenze del carattere, metacarattere o sottoespressione precedente.
| Iteratori | |
|---|---|
| Espressione | Risultato |
* |
Zero o più volte ("avidità/greedy"), analogo a {0,} |
+ |
Una o più volte ("avidità/greedy"), analogo a {1,} |
? |
Zero o una volta ("avidità/greedy"), analogo a {0,1} |
{n} |
Esattamente n volte ("avidità/greedy") |
{n,} |
Almeno n volte ("avidità/greedy") |
{n,m} |
Almeno n volte ma non più di m volte ("avidità/greedy") |
*? |
Zero o più volte ("non-greedy"), analogo a {0,}? |
+? |
Una o più volte ("non-greedy"), analogo a {1,}? |
?? |
Zero o una volta ("non-greedy"), analogo a {0,1}? |
{n}? |
Esattamente n volte ("non-greedy") |
{n,}? |
Almeno n volte ("non-greedy") |
{n,m}? |
Almeno n volte ma non più di m volte ("non-greedy") |
Pertanto, i numeri all'interno delle parentesi graffe nella forma {n,m} specificano il numero minimo di volte n e il numero massimo di volte m che l'elemento deve corrispondere.
La forma {n} equivale a {n,n} e corrisponde esattamente a n volte.
La forma {n,} corrisponde a n o più volte.
Non vi sono limiti alla grandezza di n o m, tuttavia valori elevati possono rallentare l'esecuzione e consumare più memoria.
Se le parentesi graffe appaiono in qualsiasi altro contesto, verranno trattate come caratteri normali.
Ecco alcuni esempi:
| Esempi di iteratori | |
|---|---|
| Espressione | Risultato |
foob.*r |
Corrisponde a stringhe come foobar, foobalkjdflkj9r e foobr |
foob.+r |
Corrisponde a stringhe come foobar, foobalkjdflkj9r, ecc., ma non a foobr |
foob.?r |
Corrisponde a stringhe come foobar, foobbr e foobr, ma non a foobalkj9r |
fooba{2}r |
Corrisponde alla stringa foobaar |
fooba{2,}r |
Corrisponde a stringhe come foobaar, foobaaar, foobaaaar, ecc. |
fooba{2,3}r |
Corrisponde a stringhe come foobaar o foobaaar, ma non a foobaaaar |
Una breve spiegazione sul comportamento "greedy" (avido).
La modalità "greedy" acquisisce la massima quantità possibile di elementi, mentre la modalità "non-greedy" ne acquisisce la minima quantità possibile.
Ad esempio, applicando b+ e b* alla stringa abbbbc si otterrà bbbb, mentre con b+? si otterrà b, con b*? si otterrà una stringa vuota, con b{2,3}? si otterrà bb e con b{2,3} si otterrà bbb.
È possibile impostare tutti gli iteratori in modalità "non-greedy" (si veda il modificatore g).
È possibile utilizzare il carattere | per separare una serie di alternative all'interno di un criterio di ricerca, in modo che fee|fie|foe corrisponda a fee, fie o foe nella stringa target (lo stesso vale per f(e|i|o)e).
La prima alternativa include tutto ciò che si trova tra il delimitatore di criterio precedente ((, [ o l'inizio del criterio) e il primo carattere |, mentre l'ultima alternativa include tutto ciò che si trova tra l'ultimo carattere | e il delimitatore di criterio successivo.
Pertanto, rappresenta una buona norma racchiudere le alternative tra parentesi per ridurre al minimo la confusione in merito ai loro punti di inizio e fine.
Le alternative vengono valutate da sinistra a destra, pertanto verrà scelta la prima alternativa che consente la corrispondenza dell'intera espressione.
Ciò significa che le alternative non sono necessariamente di tipo greedy.
Ad esempio: confrontando il criterio foo|foot con la stringa barefoot, solo la parte foo corrisponderà, in quanto rappresenta la prima alternativa valutata e la sua corrispondenza ha avuto successo. (Questo comportamento potrebbe non essere rilevante qualora si utilizzino le parentesi per catturare il testo corrispondente).
Si ricordi inoltre che il carattere | all'interno delle parentesi quadre viene interpretato alla lettera: pertanto, scrivendo [fee|fie|foe], la corrispondenza avverrà esclusivamente con i caratteri [feio|].
Esempio:
| Esempi di alternative | |
|---|---|
| Espressione | Risultato |
foo(bar|foo) |
Corrisponde alla stringa foobar o foofoo |
La struttura tra parentesi ( ... ) può essere utilizzata anche per definire sottoespressioni di un'espressione regolare.
Una volta eseguita la ricerca, è possibile richiamare qualsiasi sottoespressione o utilizzarla come maschera.
Le sottoespressioni vengono numerate da sinistra a destra in base alla parentesi aperta corrispondente.
La prima sottoespressione è numerata come 1, ed è supportato un massimo di 90 sottoespressioni (l'intera espressione regolare corrispondente è identificata con il numero 0 e può essere richiamata tramite $0 o $&).
Ecco alcuni esempi:
| Sottoespressioni | |
|---|---|
| Espressione | Risultato |
(foobar){8,10} |
Corrisponde a una stringa contenente 8, 9 o 10 istanze di foobar |
foob([0-9]|a+)r |
Corrisponde a foob0r, foob1r, foobar, foobaar, foobaaar, ecc. |
Note relative al modello "Sostituisci con":
$ o \ nel modello, farli precedere da \.1\$ is $2\\rub\\ restituirà 1$ is <subexpr2>\rub\.$n, è necessario racchiudere n tra parentesi graffe {}.a$12bc restituirà a<subexpr12>bc, mentre a${1}2bc restituirà a<subexpr1>2bc.Esempio:
Proviamo a invertire la data 21.01.2018 in 2018.01.21:
Cerca: (\d{2})\.(\d{2})\.(\d{4})
Sostituisci con: $3.$2.$1
I metacaratteri da \1 a \9 vengono interpretati come riferimenti retroattivi (backreference). Il codice \n corrisponde alla sottoespressione n precedentemente individuata.
Ecco alcuni esempi:
| Esempi di riferimenti retroattivi | |
|---|---|
| Espressione | Risultato |
(.)\1+ |
Corrisponde a aaaa e cc |
(.+)\1+ |
Corrisponde anche a abab e 123123 |
(['"]?)(\d+)\1 |
Corrisponde a "13" (tra virgolette doppie), '4' (tra virgolette singole), 77 (senza virgolette), ecc. |
Lookahead positivo: foo(?=bar) corrisponde a foo solo se seguito da bar, ma la parte bar non verrà inclusa nella corrispondenza.
Lookahead negativo: foo(?!bar) corrisponde a foo solo se non è seguito da bar.
Lookbehind positivo: (?<=foo)bar corrisponde a bar solo se preceduto da foo, ma la parte foo non verrà inclusa nella corrispondenza.
Lookbehind negativo: (?<!foo)bar corrisponde a bar solo se non è preceduto da foo.
Limitazioni:
Le parentesi di lookahead devono essere posizionate alla fine dell'espressione, mentre le parentesi di lookbehind devono essere all'inizio. Pertanto, non sono supportate asserzioni all'interno di scelte separate da | o all'interno di gruppi.
Per il lookbehind (?<!foo)bar, l'espressione regolare foo deve essere di lunghezza fissa (ovvero deve corrispondere solo a elementi con lunghezza costante). Non è consentito l'uso di quantificatori, ad eccezione delle parentesi graffe con cifre di ripetizione fisse {n} o {n,n}. In questa sede sono ammesse le classi di caratteri, l'uso del punto, nonché \b e \B. Non sono invece ammessi gruppi e scelte.
Per le altre tre tipologie di asserzione, l'espressione all'interno delle parentesi può presentare qualsiasi livello di complessità.
Sintassi: (?:expr).
Questa tipologia di gruppo non dispone di un "indice" e non risulta visibile ai riferimenti retroattivi. Si utilizzano i gruppi non catturanti qualora si desideri raggruppare delle sottoespressioni senza tuttavia memorizzarle come parte catturata o corrispondente della stringa. L'impiego dei gruppi non catturanti consente di velocizzare l'elaborazione delle espressioni regolari.
| Gruppi non catturanti | |
|---|---|
| Espressione | Risultato |
(https?|ftp)://([^/\r\n]+) |
In https://doublecmd.sourceforge.io individua https e doublecmd.sourceforge.io |
(?:https?|ftp)://([^/\r\n]+) |
In https://doublecmd.sourceforge.io individua esclusivamente doublecmd.sourceforge.io |
Sintassi: (?>expr|expr|...).
I gruppi atomici rappresentano un caso speciale di gruppi non catturanti: se una parte dello schema viene individuata, questa tipologia di raggruppamento disabilita il backtracking all'interno del gruppo tra parentesi. I gruppi atomici operano in modo estremamente rapido e si rivelano molto utili per ottimizzare gruppi contenenti svariate espressioni differenti.
Ad esempio, il criterio a(bc|b)c corrisponde a abcc e abc, mentre a(?>bc|b)c corrisponde a abcc ma non a abc, poiché al motore viene vietato di effettuare il backtracking per tentare di impostare il gruppo su b.
Lo standard Unicode assegna un nome alle categorie di caratteri, rappresentato da stringhe di due lettere. Ad esempio, Lu indica una lettera maiuscola, mentre Ll indica una lettera minuscola. La categoria principale a singola lettera L comprende invece tutte le lettere.
| Categorie Unicode | |
|---|---|
| Categoria | Descrizione |
L | Lettere |
Lu | Lettere maiuscole |
Ll | Lettere minuscole |
Lt | Lettere in formato Titlecase |
Lm | Lettere modificatrici |
Lo | Altre lettere |
M | Marchi / Segni diacritici |
Mn | Segni diacritici senza spazio |
Mc | Segni di combinazione con spazio |
Me | Segni racchiusi |
N | Numeri |
Nd | Cifre decimali |
Nl | Numeri rappresentati da lettere |
No | Altri numeri |
P | Punteggiatura |
Pc | Punteggiatura di connessione |
Pd | Punteggiatura di trattino |
Ps | Parentesi aperte |
Pe | Parentesi chiuse |
Pi | Virgolette aperte |
Pf | Virgolette chiuse |
Po | Altra punteggiatura |
S | Simboli |
Sm | Simboli matematici |
Sc | Simboli monetari |
Sk | Simboli modificatori |
So | Altri simboli |
Z | Separatori |
Zs | Separatori di spazio |
Zl | Separatori di riga |
Zp | Separatori di paragrafo |
C | Altri caratteri |
Cc | Caratteri di controllo |
Cf | Formato |
Cs | Surrogati |
Co | Uso privato |
Cn | Non assegnato |
Il metacarattere \p rappresenta un carattere Unicode appartenente alla categoria specificata. Sintassi: \pL e \p{L} per i nomi a singola lettera, \p{Lu} per i nomi a due lettere.
Il metacarattere \P rappresenta la negazione, indicando un carattere Unicode che non appartiene alla categoria specificata.
Questi metacaratteri sono supportati anche all'interno delle classi di caratteri.
Sintassi per un singolo modificatore: (?i) indica l'attivazione, mentre (?-i) indica la disattivazione. Sono ammessi modificatori multipli, ad esempio: (?msgxr-imsgxr).
I modificatori vengono impiegati per alterare il comportamento dell'espressione regolare. Un modificatore influisce esclusivamente sulla parte dell'espressione regolare che segue l'operatore (?imsgxr-imsgxr).
Ciascuno di questi modificatori può essere incorporato direttamente all'interno dell'espressione regolare. Se un modificatore viene inserito in linea in una sottoespressione, influirà esclusivamente su tale sottoespressione.
^ e $ in modo che corrispondano rispettivamente all'inizio o alla fine di qualsiasi riga interna alla stringa, anziché all'inizio o alla fine assoluti dell'intero testo. Si veda anche la sezione Separatori di riga. Disattivato per impostazione predefinita.. in modo che corrisponda a qualsiasi carattere, compresi i separatori di riga (si veda anche la sezione Separatori di riga), che normalmente verrebbero esclusi. Attivo per impostazione predefinita.g viene disattivato, + opererà come +?, * come *?, ecc.а-я includerà in aggiunta la lettera russa ё, l'intervallo А-Я includerà la lettera Ё, e l'intervallo а-Я comprenderà tutte le lettere russe. Attivo per impostazione predefinita.text viene ignorata. Si noti che TRegExpr chiude il commento non appena rileva il carattere ), pertanto non è possibile inserire una parentesi tonda chiusa all'interno del testo del commento.Ecco alcuni esempi:
| Esempi di estensioni Perl | |
|---|---|
| Espressione | Risultato |
(?i)Saint-Petersburg |
Corrisponde a Saint-petersburg e a Saint-Petersburg |
(?i)Saint-(?-i)Petersburg |
Corrisponde a Saint-Petersburg ma non a Saint-petersburg |
(?i)(Saint-)?Petersburg |
Corrisponde a Saint-petersburg e a saint-petersburg |
((?i)Saint-)?Petersburg |
Corrisponde a saint-Petersburg ma non a saint-petersburg |
Il modificatore x merita una spiegazione più approfondita.
Esso indica di ignorare i caratteri di spazio che non sono preceduti da barra rovesciata e che non si trovano all'interno di una classe di caratteri.
È possibile utilizzarlo per suddividere l'espressione regolare in parti (leggermente) più leggibili.
Anche il carattere # viene trattato come metacarattere per introdurre commenti, ad esempio:
(
(abc) # Commento 1
| # È possibile utilizzare lo spazio per formattare l'espressione regolare: TRegExpr lo ignorerà
(efg) # Commento 2
)
Questo significa inoltre che se si desidera includere un carattere di spazio letterale o il carattere # nel criterio (al di fuori delle classi di caratteri, dove non sono influenzati dal modificatore x), sarà necessario farli precedere da barra rovesciata o codificarli tramite escape ottale o esadecimale.
Nel complesso, queste funzionalità incrementano in modo significativo la leggibilità delle espressioni regolari.