Bash
Pattern matching ed espressioni regolari
Ricerca…
Sintassi
- $ shopt -u option # Disattiva l'opzione incorporata di Bash
- Opzione $ shopt -s # Attiva l'opzione incorporata di Bash
Osservazioni
Classi di caratteri
Le classi di caratteri valide per il []
glob sono definite dallo standard POSIX:
alnum alpha ascii blank cntrl cifra grafico inferiore stampa punct spazio parola superiore xdigit
All'interno []
più di una classe o intervallo di caratteri, ad es.
$ echo a[a-z[:blank:]0-9]*
corrisponderà a qualsiasi file che inizia con un a
ed è seguito da una lettera minuscola o uno spazio o una cifra.
Va tenuto presente, tuttavia, che un []
glob può essere completamente negato e non solo parti di esso. Il carattere di negazione deve essere il primo carattere che segue l'apertura [
, ad esempio, questa espressione corrisponde a tutti i file che non iniziano con un a
$ echo [^a]*
Quanto segue corrisponde a tutti i file che iniziano con una cifra o una ^
$ echo [[:alpha:]^a]*
Essa non corrisponde a qualsiasi file o cartella che inizia con la lettera con la eccezione di un a
perché l' ^
viene interpretato come un letterale ^
.
Escaping caratteri glob
È possibile che un file o una cartella contenga un carattere glob come parte del suo nome. In questo caso un glob può essere sfuggito con un \
ordine precedente per una corrispondenza letterale. Un altro approccio consiste nell'usare virgolette doppie ""
o singole ''
per indirizzare il file. Bash non elabora i glob che sono racchiusi tra ""
o ''
.
Differenza rispetto alle espressioni regolari
La differenza più significativa tra i glob e le espressioni regolari è che un'espressione regolare valida richiede un qualificatore e un quantificatore. Un qualificatore identifica cosa abbinare e un quantificatore indica quanto spesso abbinare il qualificatore. La RegEx equivalente al *
glob è .*
Dove .
indica qualsiasi carattere e *
indica zero o più corrispondenze del carattere precedente. Il RegEx equivalente per il ?
glob è .{1}
. Come prima, il qualificatore .
corrisponde a qualsiasi carattere e {1}
indica di corrispondere esattamente alla volta del qualificatore precedente. Questo non dovrebbe essere confuso con il ?
quantificatore, che corrisponde a zero o una volta in una RegEx. []
Glob può essere utilizzato nello stesso modo in un RegEx, purché sia seguito da un quantificatore obbligatorio.
Espressioni regolari equivalenti
glob | RegEx |
---|---|
* | .* |
? | . |
[] | [] |
Controlla se una stringa corrisponde a un'espressione regolare
Controlla se una stringa consiste in esattamente 8 cifre:
$ date=20150624
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
yes
$ date=hello
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
no
Il * glob
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
L'asterisco * è probabilmente il glob più usato. Si abbina semplicemente a qualsiasi stringa
$ echo *acy
macy stacy tracy
Un singolo * non corrisponderà a file e cartelle che si trovano nelle sottocartelle
$ echo *
emptyfolder folder macy stacy tracy
$ echo folder/*
folder/anotherfolder folder/subfolder
Il ** glob
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -s globstar
Bash è in grado di interpretare due asterischi adiacenti come un singolo glob. Con l'opzione globstar
attivata, questa può essere utilizzata per abbinare le cartelle che risiedono più in profondità nella struttura delle directory
echo **
emptyfolder folder folder/anotherfolder folder/anotherfolder/content folder/anotherfolder/content/deepfolder folder/anotherfolder/content/deepfolder/file folder/subfolder folder/subfolder/content folder/subfolder/content/deepfolder folder/subfolder/content/deepfolder/file macy stacy tracy
Il **
può essere pensato per un'espansione del percorso, indipendentemente dalla profondità del percorso. Questo esempio corrisponde a qualsiasi file o cartella che inizia con deep
, indipendentemente da quanto è nidificato in profondità:
$ echo **/deep*
folder/anotherfolder/content/deepfolder folder/subfolder/content/deepfolder
Il ? glob
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Il ?
corrisponde semplicemente esattamente a un personaggio
$ echo ?acy
macy
$ echo ??acy
stacy tracy
[] Glob
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Se è necessario abbinare caratteri specifici, è possibile utilizzare '[]'. Qualsiasi carattere all'interno di '[]' verrà abbinato esattamente una volta.
$ echo [m]acy
macy
$ echo [st][tr]acy
stacy tracy
Il []
glob, tuttavia, è più versatile di quello. Inoltre, consente una corrispondenza negativa e persino l'abbinamento di intervalli di caratteri e classi di caratteri. Si ottiene una corrispondenza negativa usando !
o ^
come primo carattere che segue [
. Siamo in grado di abbinare stacy
da
$ echo [!t][^r]acy
stacy
Qui stiamo dicendo bash che vogliamo abbinare solo i file che non iniziano con una t
e la seconda lettera non è una r
e il file termina in acy
.
Gli intervalli possono essere abbinati separando una coppia di caratteri con un trattino ( -
). Qualsiasi personaggio che rientra tra questi due caratteri inclusi - inclusi - sarà abbinato. Ad esempio, [rt]
è equivalente a [rst]
$ echo [r-t][r-t]acy
stacy tracy
Le classi di caratteri possono essere abbinate da [:class:]
, ad esempio, per abbinare i file che contengono uno spazio bianco
$ echo *[[:blank:]]*
file with space
Corrispondenza di file nascosti
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
L'opzione built-in di Bash dotglob consente di abbinare file e cartelle nascosti, ad es. File e cartelle che iniziano con a .
$ shopt -s dotglob
$ echo *
file with space folder .hiddenfile macy stacy tracy
Maiuscole / minuscole
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
L'impostazione dell'opzione nocaseglob
corrisponderà al glob in modo insensibile alle maiuscole / minuscole
$ echo M*
M*
$ shopt -s nocaseglob
$ echo M*
macy
Comportamento quando un glob non corrisponde a nulla
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Nel caso in cui il glob non corrisponda a nulla il risultato è determinato dalle opzioni nullglob
e failglob
. Se nessuno di essi è impostato, Bash restituirà il glob stesso se non vi è alcuna corrispondenza
$ echo no*match
no*match
Se viene attivato nullglob
viene nullglob
nulla ( null
):
$ shopt -s nullglob
$ echo no*match
$
Se viene attivato failglob
viene failglob
un messaggio di errore:
$ shopt -s failglob
$ echo no*match
bash: no match: no*match
$
Si noti che l'opzione failglob
sostituisce l'opzione nullglob
, ovvero se nullglob
e failglob
sono entrambi impostati, quindi, in caso di mancata corrispondenza, viene restituito un errore.
Globbing esteso
Preparazione
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
L'opzione extglob
incorporata di Bash può estendere le capacità di corrispondenza di un glob
shopt -s extglob
I seguenti sotto-modelli comprendono globi estesi validi:
-
?(pattern-list)
- Corrisponde a zero o a una ricorrenza dei pattern specificati -
*(pattern-list)
- Corrisponde a zero o più occorrenze dei pattern specificati -
+(pattern-list)
- Corrisponde a una o più occorrenze dei modelli specificati -
@(pattern-list)
- Trova uno dei modelli indicati -
!(pattern-list)
- Trova qualsiasi cosa tranne uno dei modelli indicati
L' pattern-list
è un elenco di globs separati da |
.
$ echo *([r-t])acy
stacy tracy
$ echo *([r-t]|m)acy
macy stacy tracy
$ echo ?([a-z])acy
macy
Lo stesso pattern-list
può essere un altro glob esteso nidificato. Nell'esempio precedente abbiamo visto che possiamo abbinare tracy
e stacy
con *(rt)
. Questo glob esteso può essere utilizzato all'interno del glob esteso negato !(pattern-list)
per corrispondere a macy
$ echo !(*([r-t]))acy
macy
Corrisponde a tutto ciò che non inizia con zero o più occorrenze delle lettere r
, s
e t
, che lascia solo la corrispondenza macy
possibile.
Corrispondenza Regex
pat='[^0-9]+([0-9]+)'
s='I am a string with some digits 1024'
[[ $s =~ $pat ]] # $pat must be unquoted
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"
Produzione:
I am a string with some digits 1024
1024
Invece di assegnare la regex a una variabile ( $pat
) potremmo fare anche:
[[ $s =~ [^0-9]+([0-9]+) ]]
Spiegazione
- Il costrutto
[[ $s =~ $pat ]]
esegue la corrispondenza regex - I gruppi catturati, ovvero i risultati della corrispondenza, sono disponibili in un array denominato BASH_REMATCH
- L'indice 0 nell'array BASH_REMATCH è la corrispondenza totale
- La esimo indice nell'array BASH_REMATCH rappresenta l'i-esimo gruppo catturato, dove i = 1, 2, 3 ...
Ottieni gruppi catturati da una corrispondenza regolare su una stringa
a='I am a simple string with digits 1234'
pat='(.*) ([0-9]+)'
[[ "$a" =~ $pat ]]
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"
echo "${BASH_REMATCH[2]}"
Produzione:
I am a simple string with digits 1234
I am a simple string with digits
1234