Bash
Correspondance de motif et expressions régulières
Recherche…
Syntaxe
- $ shopt -u option # Désactiver l'option intégrée de Bash
- $ shopt -s option # Activer l'option intégrée de Bash
Remarques
Classes de personnages
Les classes de caractères valides pour le glob []
sont définies par le standard POSIX:
alnum alpha ascii blank cntrl digit graphe inférieur imprimer espace ponctuel mot supérieur xdigit
À l'intérieur de []
plus d'une classe ou plage de caractères peut être utilisée, par exemple,
$ echo a[a-z[:blank:]0-9]*
correspondra à tout fichier commençant par a
et suivi d'une lettre minuscule ou d'un blanc ou d'un chiffre.
Il faut toutefois garder à l’esprit qu’un []
glob ne peut être totalement nié et pas seulement des parties de celui-ci. Le caractère négatif doit être le premier caractère après l'ouverture [
, par exemple, cette expression correspond à tous les fichiers qui ne commencent pas par a
$ echo [^a]*
Ce qui suit correspond à tous les fichiers qui commencent par un chiffre ou un ^
$ echo [[:alpha:]^a]*
Il ne correspond à aucun fichier ou un dossier qui commence par la lettre , sauf un a
parce que le ^
est interprété comme un littéral ^
.
Caractères de globes échappant
Il est possible qu'un fichier ou un dossier contienne un caractère glob dans le cadre de son nom. Dans ce cas, un glob peut être échappé avec un \
précédent pour une correspondance littérale. Une autre approche consiste à utiliser ''
guillemets doubles ""
ou simples ''
pour traiter le fichier. Bash ne traite pas les globes entourés par ""
ou ''
.
Différence avec les expressions régulières
La différence la plus significative entre les globes et les expressions régulières est qu'une expression régulière valide nécessite un qualificatif ainsi qu'un quantificateur. Un qualificatif identifie ce qui doit correspondre et un quantificateur indique à quelle fréquence il doit correspondre au qualificatif. Le RegEx équivalent au *
glob est .*
Où .
signifie n'importe quel caractère et *
signifie zéro ou plusieurs correspondances du caractère précédent. L'équivalent RegEx pour le ?
glob est .{1}
. Comme avant, le qualificatif .
correspond à n'importe quel caractère et le {1}
indique qu'il doit correspondre exactement au qualificateur précédent. Cela ne doit pas être confondu avec le ?
quantifier, qui correspond à zéro ou une fois dans un RegEx. Le []
glob est utilisable de la même manière dans un RegEx, à condition qu'il soit suivi d'un quantificateur obligatoire.
Expressions régulières équivalentes
Glob | RegEx |
---|---|
* | .* |
? | . |
[] | [] |
Vérifier si une chaîne correspond à une expression régulière
Vérifiez si une chaîne contient exactement 8 chiffres:
$ date=20150624
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
yes
$ date=hello
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
no
Le * glob
Préparation
$ 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'astérisque * est probablement le glob le plus utilisé. Il correspond simplement à n'importe quelle chaîne
$ echo *acy
macy stacy tracy
Un seul * ne correspondra pas aux fichiers et dossiers qui résident dans les sous-dossiers
$ echo *
emptyfolder folder macy stacy tracy
$ echo folder/*
folder/anotherfolder folder/subfolder
Le ** glob
Préparation
$ 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 est capable d'interpréter deux astérisques adjacents en un seul glob. Avec l'option globstar
activée, cela peut être utilisé pour faire correspondre les dossiers qui résident plus profondément dans la structure des répertoires.
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
Le **
peut être considéré comme une extension de chemin, quelle que soit la profondeur du chemin. Cet exemple correspond à tout fichier ou dossier qui commence par deep
, quelle que soit sa profondeur d'imbrication:
$ echo **/deep*
folder/anotherfolder/content/deepfolder folder/subfolder/content/deepfolder
Le ? glob
Préparation
$ 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
Le ?
correspond simplement à un caractère
$ echo ?acy
macy
$ echo ??acy
stacy tracy
Le [] glob
Préparation
$ 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
S'il est nécessaire de faire correspondre des caractères spécifiques, «[]» peut être utilisé. Tout caractère à l'intérieur de '[]' sera comparé exactement une fois.
$ echo [m]acy
macy
$ echo [st][tr]acy
stacy tracy
Le []
glob, cependant, est plus polyvalent que cela. Il permet également une correspondance négative et même des plages de caractères et de classes de caractères correspondantes. Une correspondance négative est obtenue en utilisant !
ou ^
comme premier caractère suivant [
. Nous pouvons faire correspondre stacy
par
$ echo [!t][^r]acy
stacy
Nous disons ici bash que nous voulons faire correspondre uniquement les fichiers qui ne commencent pas par un t
et que la deuxième lettre n'est pas un r
et que le fichier se termine par acy
.
Les plages peuvent être comparées en séparant une paire de caractères avec un tiret ( -
). Tout caractère compris entre ces deux caractères - inclus - sera mis en correspondance. Par exemple, [rt]
est équivalent à [rst]
$ echo [r-t][r-t]acy
stacy tracy
Les classes de caractères peuvent être appariées par [:class:]
, par exemple, pour correspondre à des fichiers contenant un espace
$ echo *[[:blank:]]*
file with space
Faire correspondre les fichiers cachés
Préparation
$ 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'option intégrée Bash dotglob permet de faire correspondre les fichiers et dossiers cachés, c'est-à-dire les fichiers et les dossiers qui commencent par un .
$ shopt -s dotglob
$ echo *
file with space folder .hiddenfile macy stacy tracy
Correspondance insensible à la casse
Préparation
$ 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
La définition de l'option nocaseglob
correspondra au glob dans une nocaseglob
insensible à la casse
$ echo M*
M*
$ shopt -s nocaseglob
$ echo M*
macy
Comportement lorsqu'un glob ne correspond à rien
Préparation
$ 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
Si le glob ne correspond à rien, le résultat est déterminé par les options nullglob
et failglob
. Si aucun d'eux n'est défini, Bash retournera le glob lui-même si rien ne correspond
$ echo no*match
no*match
Si nullglob
est activé, rien ( null
) n'est renvoyé:
$ shopt -s nullglob
$ echo no*match
$
Si failglob
est activé, un message d'erreur est renvoyé:
$ shopt -s failglob
$ echo no*match
bash: no match: no*match
$
Notez que l'option failglob
remplace l'option nullglob
, c'est-à-dire que si nullglob
et failglob
sont tous deux définis, une erreur est renvoyée en cas de non-correspondance.
Globe étendu
Préparation
$ 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'option extglob
de extglob
peut étendre les capacités de correspondance d'un glob
shopt -s extglob
Les sous-modèles suivants comprennent des globes étendus valides:
-
?(pattern-list)
- Correspond à zéro ou à une occurrence des motifs donnés -
*(pattern-list)
- Correspond à zéro ou plusieurs occurrences des patterns donnés -
+(pattern-list)
- Correspond à une ou plusieurs occurrences des patterns donnés -
@(pattern-list)
- Correspond à l'un des motifs donnés -
!(pattern-list)
- Correspond à tout sauf un des motifs donnés
La pattern-list
est une liste de globes séparés par |
.
$ echo *([r-t])acy
stacy tracy
$ echo *([r-t]|m)acy
macy stacy tracy
$ echo ?([a-z])acy
macy
La pattern-list
même peut être un autre glob étendu imbriqué. Dans l'exemple ci-dessus, nous avons vu que nous pouvons faire correspondre tracy
et stacy
avec *(rt)
. Ce glob étendu lui-même peut être utilisé à l’intérieur du glob étendu négatif !(pattern-list)
afin de correspondre à macy
$ echo !(*([r-t]))acy
macy
Il correspond à tout ce qui ne commence pas par zéro ou plusieurs occurrences des lettres r
, s
et t
, ce qui ne laisse que la correspondance possible entre macy
.
Regex correspondant
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]}"
Sortie:
I am a string with some digits 1024
1024
Au lieu d’affecter la regex à une variable ( $pat
), nous pourrions aussi faire:
[[ $s =~ [^0-9]+([0-9]+) ]]
Explication
- La construction
[[ $s =~ $pat ]]
effectue la correspondance de regex - Les groupes capturés, c'est-à-dire les résultats de la correspondance, sont disponibles dans un tableau nommé BASH_REMATCH.
- Le 0ème index du tableau BASH_REMATCH correspond à la correspondance totale
- Le iʻeme index du tableau BASH_REMATCH est le iʻeme groupe capturé, où i = 1, 2, 3 ...
Obtenir des groupes capturés à partir d'une correspondance regex avec une chaîne
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]}"
Sortie:
I am a simple string with digits 1234
I am a simple string with digits
1234