This is a machine translation based on the English version of the article. It might or might not have already been subject to text preparation. If you find errors, please file a GitHub issue that states the paragraph that has to be improved. |
1. Introduzione
Le espressioni regolari — regex (o, più raramente, regexp) — vengono utilizzate in Checkmk per specificare i nomi dei servizi e in molte altre situazioni.
Si tratta di modelli che corrispondono a un determinato testo o che non corrispondono (non-match).
Puoi utilizzarle per molte operazioni pratiche, come formulare regole flessibili che si applicano a tutti i servizi con foo o bar nel loro nome.
Le espressioni regolari vengono spesso confuse con i modelli di ricerca dei nomi dei file, poiché i caratteri speciali * e ?, così come le parentesi quadre e graffe, possono essere presenti in entrambi.
In questo articolo ti mostreremo le funzioni più importanti delle espressioni regolari, ovviamente nel contesto di Checkmk. Dato che Checkmk utilizza due componenti diverse per le espressioni regolari, a volte il diavolo si nasconde nei dettagli. In sostanza, il nucleo di monitoraggio utilizza la libreria C e tutti gli altri componenti utilizzano Python 3. Laddove esistono differenze, te le spiegheremo.
In Checkmk, le espressioni regolari sono consentite nei campi di immissione dati su varie pagine. Se non sei sicuro, usa l’aiuto contestuale tramite il menu “Help” (Help > Show inline help). Lì puoi vedere se le espressioni regolari sono consentite e come possono essere utilizzate. |
Quando si lavora con plug-in più vecchi o provenienti da fonti esterne, può capitare che questi utilizzino Python 2 o Perl e si discostino dalle convenzioni qui descritte.
In questo articolo ti mostreremo le funzionalità più importanti delle espressioni regolari, ma non certo tutte. Se le possibilità illustrate qui non ti bastano, di seguito troverai alcuni riferimenti dove potrai leggere tutti i dettagli rilevanti. E poi c'è sempre internet.
Se vuoi programmare i tuoi plug-in che, ad esempio, utilizzano espressioni regolari per individuare anomalie nei file di log, puoi usare questo articolo come base. Tuttavia, quando si effettuano ricerche in grandi volumi di dati, l'ottimizzazione della performance è un aspetto importante. In caso di dubbio, consulta sempre la documentazione della libreria regex che stai utilizzando.
2. Lavorare con le espressioni regolari
In questa sezione useremo esempi concreti per mostrare come lavorare con le espressioni regolari, dalle semplici corrispondenze di singoli caratteri o stringhe, fino a gruppi complessi di caratteri.
2.1. Caratteri alfanumerici
Con le espressioni regolari, si tratta sempre di verificare se un modello corrisponde a un determinato testo (ad es. il nome del servizio). L'esempio di applicazione più semplice è una sequenza di caratteri alfanumerici. Questi (e il segno meno usato come trattino) corrispondono semplicemente a se stessi in un'espressione.
Quando si effettua una ricerca nell'ambiente di monitoraggio, Checkmk di solito non fa distinzione tra maiuscole e minuscole.
Nella maggior parte dei casi, l'espressione CPU load corrisponde sia al testo CPU load che a cpu LoAd.
La ricerca nell'ambiente di configurazione, invece, di solito fa distinzione tra maiuscole e minuscole.
Sono possibili eccezioni giustificate a queste regole, descritte nell'aiuto in linea.
Nei campi di immissione senza espressione regolare in cui è specificata una corrispondenza esatta (principalmente con i nomi host), si distingue sempre tra maiuscole e minuscole! |
2.2. Il punto ( . ) come carattere jolly
Oltre alle stringhe di caratteri "in chiaro", ci sono diversi caratteri e stringhe che hanno funzioni "magiche".
Il carattere più importante è il punto (.).
Corrisponde esattamente a qualsiasi singolo carattere arbitrario:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
2.3. Ripetizione di caratteri
Molto spesso si vorrebbe definire che possa verificarsi una sequenza di caratteri di una certa lunghezza. A questo scopo si specifica il numero di ripetizioni del carattere precedente tra parentesi graffe:
| Espressione regolare | Funzione | Corrispondenza | Nessuna corrispondenza |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Esistono delle abbreviazioni per le ultime tre condizioni sopra indicate:
*corrisponde al carattere precedente un numero qualsiasi di volte, + corrisponde ad almeno un'occorrenza e ? corrisponde al massimo a un'occorrenza.
Puoi anche usare il punto . con gli operatori di ripetizione per cercare una sequenza di caratteri arbitrari in modo più definito:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.4. Classi di caratteri, numeri e lettere
Le classi di caratteri consentono di corrispondere in determinate sezioni del set di caratteri, ad esempio "qui deve esserci una cifra". Per farlo, metti tutti i caratteri da cercare tra parentesi quadre. Con il segno meno puoi anche specificare intervalli. Nota: si applica la sequenza del set di caratteri ASCII a 7 bit.
Ad esempio, [abc] sta per esattamente uno dei caratteri a, b o c, e [0-9] per qualsiasi cifra — entrambi possono essere combinati.
È possibile anche una negazione dell'insieme — con un ^ tra parentesi, [^abc] sta quindi per qualsiasi carattere tranne a, b, c.
Le classi di caratteri possono ovviamente essere combinate con altri operatori. Cominciamo con alcuni esempi astratti:
| Classe di caratteri | Funzione |
|---|---|
|
Esattamente uno dei caratteri a, b, c. |
|
Esattamente una cifra, una lettera minuscola o un trattino basso. |
|
Qualsiasi carattere tranne a, b, c. |
|
Esattamente un carattere, che va da uno spazio a un trattino, conforme allo standard ASCII. I seguenti caratteri rientrano in questo intervallo: |
|
Una sequenza di almeno una e al massimo 20 lettere e/o cifre in qualsiasi ordine. |
Ecco alcuni esempi pratici:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Se hai bisogno di uno dei caratteri |
2.5. Inizio e fine — prefisso, suffisso e infisso
In molti casi è necessario distinguere tra corrispondenze all'inizio, alla fine o semplicemente in un punto qualsiasi all'interno di una stringa.
Per una corrispondenza all'inizio di una stringa (match inizio parola (prefisso)) usa l'^o (circonflesso), per la fine (match fine parola (suffisso)) usa l'$o (segno del dollaro).
Se nessuno di questi operatori è specificato, la maggior parte delle librerie di espressioni regolari usa il match parziale come impostazione predefinita — viene cercato in qualsiasi punto della stringa di caratteri.
Per una corrispondenza esatta, usa sia ^ che $.
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Nel monitoraggio e nella Console degli Eventi, il match parziale è lo standard. Nel monitoraggio, il match parziale è lo standard. Vengono trovate le espressioni che compaiono in qualsiasi punto del testo, ovvero la ricerca di "memory" trova anche "kernel memory". Nella GUI di Setup, invece, quando si confrontano espressioni regolari con nomi dei servizi e altre cose, Checkmk controlla fondamentalmente se l'espressione corrisponde all'inizio del testo (match inizio parola (prefisso)) — questo è solitamente ciò che stai cercando:

Se hai bisogno di un match parziale in punti in cui è previsto il match inizio parola (prefisso), basta estendere l'espressione regolare con .* all'inizio per trovare qualsiasi stringa prefissata:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
|
|
|
Suggerimento: puoi anteporre a qualsiasi ricerca all'inizio di una stringa ^ e a qualsiasi ricerca all'interno di una stringa .* ,
gli interpreti delle espressioni regolari ignoreranno i simboli ridondanti.
2.6. Mascherare i caratteri speciali con una barra rovesciata
Dato che il punto corrisponde a tutto, ovviamente corrisponde anche a un punto.
Se ora vuoi trovare esattamente un punto, devi mascherarlo con una barra rovesciata (\).
Questo vale in modo analogo per tutti gli altri caratteri speciali.
Questi sono: \ . * + ? { } ( ) [ ] | & ^ e $.
Scrivere una barra rovesciata \ fa sì che il carattere speciale che la segue venga trattato come un carattere normale:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
|
|
|
Attenzione Python: poiché in Python la barra rovesciata nella rappresentazione interna della stringa viene mascherata internamente con un'altra barra rovesciata, queste due barre rovesciate devono essere mascherate nuovamente, il che porta a un totale di quattro barre rovesciate:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
2.7. Valori alternativi
Con la barra verticale | puoi definire delle alternative, ovvero usare un'operazione OR:
1|2|3corrisponde a 1, 2 o 3.
Se hai bisogno di tali alternative nel mezzo di un'espressione, raggruppale tra parentesi tonde:
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
|
|
|
2.8. Gruppi di corrispondenza
I gruppi di corrispondenza (o gruppi di cattura) svolgono due funzioni:
La prima funzione è il raggruppamento di alternative o corrispondenze parziali, come mostrato nell'esempio precedente.
Sono possibili anche raggruppamenti annidati.
Inoltre, gli operatori di ripetizione *, +, ? e {…} possono essere utilizzati preceduti da parentesi tonde.
Pertanto, l'espressione (/local)?/share corrisponde sia a /local/share che a /share.
La seconda funzione è quella di "catturare" i gruppi di corrispondenza in variabili.
Nella
Console degli Eventi (EC), nella
Business Intelligence (BI), nella ridenominazione massiva degli host
e nelle mappature piggyback, c'è la possibilità di utilizzare la parte di testo
corrispondente all'espressione regolare nella prima parentesi come \1 ,
la parte corrispondente alla seconda parentesi come \2 , e così via.
L'ultimo esempio nella tabella mostra l'uso delle alternative all'interno di un gruppo di corrispondenza.
| Espressione regolare | Testo da corrispondere | Gruppo 1 | Gruppo 2 |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
L'immagine seguente mostra come rinominare più host in un'unica operazione.
Tutti i nomi host che corrispondono all'espressione regolare server-(.*)\.local verranno sostituiti con \1.servers.local.
Dove \1 sta esattamente per il testo "catturato" dall'.*e tra parentesi:

Nell'esempio concreto, server-lnx02.local viene quindi convertito in lnx02.servers.local.
Se un gruppo di corrispondenza non deve "catturare" gruppi di caratteri, ad esempio se viene utilizzato solo per strutturare, puoi usare ?: per convertirlo in un gruppo di corrispondenza non catturante (non-capturing match group): (?:/local)?/share.
2.9. Flag inline
Con i flag inline, è possibile effettuare impostazioni specifiche relative alla modalità di valutazione all'interno di un'espressione regolare.
Il più rilevante per lavorare con Checkmk è (?i), che switcha alla corrispondenza insensibile alle maiuscole/minuscole per le espressioni che altrimenti sarebbero sensibili alle maiuscole/minuscole.
In casi molto rari, potresti voler utilizzare anche (?s) e (?m) per lavorare con stringhe su più righe.
Tieni presente che dalla versione 3.11 Python si aspetta che i flag inline siano all'inizio di un'espressione regolare - (?i)somestring — oppure che specifichino l'ambito — (?i:somestring).
Dato che Checkmk in alcuni casi combina internamente le espressioni regolari per migliorare la performance, ti consigliamo vivamente di non usare i flag inline all'inizio di un'espressione regolare.
Usa invece sempre la notazione con l'ambito — che, in caso di dubbio, si estende all'intera espressione regolare:
(?i:somestring).
Questa è una variante del gruppo di corrispondenza senza cattura.
3. Tabella dei caratteri speciali
Qui troverai un elenco che riassume tutti i caratteri speciali e le funzioni delle espressioni regolari utilizzate da Checkmk, come spiegato sopra:
|
corrisponde a qualsiasi carattere. |
|
Valuta il carattere speciale successivo come un carattere normale. |
|
Il carattere precedente deve comparire esattamente cinque volte. |
|
Il carattere precedente deve comparire almeno cinque e al massimo dieci volte. |
|
Il carattere precedente può comparire un numero qualsiasi di volte (corrisponde a |
|
Il carattere precedente può comparire un numero qualsiasi di volte, ma deve comparire almeno una volta (equivalente a |
|
Il carattere precedente può comparire zero o una volta (equivalente a |
|
Rappresenta esattamente uno dei caratteri |
|
Indica esattamente uno dei caratteri |
|
Indica esattamente una cifra, una lettera minuscola o il trattino basso. |
|
Indica un carattere come eccezione, eccetto la virgoletta singola o doppia. |
|
Corrisponde alla fine di un testo. |
|
Corrisponde all'inizio di un testo. |
|
Corrisponde a |
|
Corrisponde alla sottoespressione A a un gruppo di corrispondenza. |
|
Cambia la modalità di valutazione della sottoespressione A in insensibile alle maiuscole/minuscole tramite il flag inline. |
|
Corrisponde a un tabulatore. Questo carattere compare spesso nei file di log o nelle tabelle CSV. |
|
Corrisponde a tutti gli spazi (l'ASCII utilizza 5 diversi tipi di spazio). |
I seguenti caratteri devono essere preceduti da una barra rovesciata,
se devono essere usati letteralmente: \ . * + ? { } ( ) [ ] | & ^ $.
3.1. Unicode in Python 3
In particolare, se sono stati copiati e incollati nomi propri nei commenti o nei testi descrittivi, e quindi nel testo compaiono caratteri Unicode o diversi tipi di spazi, le classi estese di Python sono molto utili:
|
Corrisponde a un tabulatore (tab), presente in parte nei file di log o nelle tabelle CSV. |
|
Corrisponde a tutti gli spazi (Unicode supporta 25 spazi diversi, ASCII 5). |
|
Inverte rispetto a |
|
Corrisponde a tutti i caratteri che fanno parte di una parola, cioè lettere, e in Unicode anche accenti, glifi cinesi, arabi o coreani. |
|
Inversione di |
Nei casi in cui Checkmk consente di corrispondere con Unicode, l'\w è particolarmente utile quando si cercano parole con ortografia simile in lingue diverse, ad esempio nomi propri che a volte sono scritti con l'accento e a volte senza.
| Espressione regolare | Corrispondenza | Nessuna corrispondenza |
|---|---|---|
|
|
|
4. Testare le espressioni regolari
La logica delle espressioni regolari non è sempre facile da capire, specialmente nel caso di gruppi di corrispondenza annidati, e quando si tratta di capire l'ordine e quale estremità della stringa deve essere abbinata. Meglio che procedere per tentativi in Checkmk, ci sono due modi per testare le espressioni regolari: Servizi online come regex101.com preparano le corrispondenze in modo grafico e spiegano l'ordine di valutazione in tempo reale:

La seconda procedura di test è il prompt di Python, che è incluso in ogni installazione di Python. Su Linux e Mac OS, Python 3 è solitamente preinstallato. Proprio perché le espressioni regolari al prompt di Python vengono valutate esattamente come in Checkmk, non ci sono discrepanze nell'interpretazione, anche in caso di nidificazioni complesse. Con il test nell'interprete Python vai sempre sul sicuro.
Dopo l'apertura, devi importare il modulo re.
Nell'esempio switchiamo la distinzione tra maiuscole e minuscole con re.IGNORECASE:
Per emulare il comportamento delle espressioni regolari di C, utilizzate anche in molti componenti Python, puoi limitarti all'ASCII:
>>> re.ASCII
re.ASCIIOra puoi usare la funzione re.match() per confrontare direttamente un'espressione regolare con una stringa e visualizzare il gruppo di corrispondenza:
group(0)indica l'intera corrispondenza, mentre group(1) indica la prima corrispondenza che corrisponde alla sottoespressione racchiusa tra parentesi tonde:
>>> x = re.match('M[ae]{1}[iy]{1}e?r', 'Meier')
>>> x.group(0)
'Meier'
>>> x = re.match('M[ae]{1}[iy]{1}e?r', 'Mayr')
>>> x.group(0)
'Mayr'
>>> x = re.match('M[ae]{1}[iy]{1}e?r', 'Myers')
>>> x.group(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: no such group
>>> x = re.match('server-(.*)\.local', 'server-lnx23.local')
>>> x.group(0)
'server-lnx23.local'
>>> x.group(1)
'lnx23'5. Documentazione esterna aggiuntiva
Ken Thompson, uno dei creatori di Unix negli anni '60, è stato il primo a sviluppare le espressioni regolari nella forma odierna, tra l'altro nel comando Unix grep, che è ancora in uso.
Da allora sono state create numerose estensioni e dialetti delle espressioni regolari, tra cui le regex estese, le regex compatibili con Perl e una variante molto simile in Python.
Nei filtri delle visualizzazioni, Checkmk utilizza le espressioni regolari estese POSIX (extended REs).
Queste vengono valutate nel nucleo di monitoraggio in C utilizzando la funzione regex della libreria C.
Puoi trovare un riferimento completo al riguardo nella pagina di manuale Linux relativa a regex(7):
In tutti gli altri contesti sono disponibili tutte le funzioni delle espressioni regolari di Python. Ciò include, tra le altre cose, le regole di configurazione , le regole di configurazione della Console degli Eventi (EC) e la Business Intelligence (BI) .
Le espressioni regolari in Python sono un'estensione delle RE estese e sono molto simili a quelle di Perl.
Supportano, ad esempio, il cosiddetto lookahead negativo, un asterisco non avido * o l'applicazione della distinzione tra maiuscole e minuscole.
I dettagli sulle funzionalità di queste espressioni regolari sono disponibili nella guida online di Python per il modulo re o, in modo più approfondito, nella documentazione online di Python:
Una spiegazione molto dettagliata delle espressioni regolari è disponibile in un articolo di Wikipedia.
