Chapitre 4. Caractères et expressions génériques

Table des matières

4.1. Caractères génériques
4.1.1. Le caractère *
4.1.2. Le caractère ?
4.1.3. Les caractères []
4.2. Expressions génériques
4.3. Autres options relatives aux caractères et expressions génériques

Les caractères et expressions génériques sont issus d'un mécanisme plus général appelé expressions rationnelles (regular expressions) ou expressions régulières. Ces caractères et expressions sont utilisés pour spécifier un modèle de noms d'entrées. Ce modèle est ensuite interprété par le shell pour créer une liste triée de noms d'entrées. Par défaut, le shell traite uniquement les entrées non cachées du répertoire courant ; cela signifie que les entrées dont le nom commence par le caractère . sont ignorées.

Pour illustrer l’utilisation des caractères et expressions génériques, on utilisera un répertoire appelé generique contenant les 16 entrées suivantes :

$ pwd
/home/sanchis/generique
$
$ ls -l
total 0
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 1
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 _a
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 a
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 A
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 à
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 ami
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 an
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 Arbre
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 e
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 é
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 émirat
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 En
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 état
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 minuit
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 zaza
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 Zoulou
$

La valeur des paramètres régionaux influe grandement sur l'interprétation et la méthode de tri des noms d’entrées. Si on utilise la locale standard, on obtient l’affichage suivant :

$ LC_ALL=C ls -l
total 0
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  1
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  A
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  Arbre
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18  En
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18  Zoulou
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  _a
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  a
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  ami
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17  an
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18  e
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18  minuit
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18  zaza
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:17 ''$'\303\240'
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18 ''$'\303\251'
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18 ''$'\303\251''mirat'
-rw-r--r-- 1 sanchis sanchis 0 Jan  6 18:18 ''$'\303\251''tat'
$

On s’aperçoit que l’interprétation des noms d’entrées contenant des caractères accentués est altérée.

L'interprétation des caractères et expressions génériques dépend de l'état de certaines options des commandes internes set et shopt de bash.

De manière générale,

  • pour connaître l'état des options de la commande interne set : set –o

  • pour activer une option de la commande interne set : set –o option

  • pour désactiver une option de la commande interne set : set +o option

  • pour connaître l'état des options de la commande interne shopt : shopt

  • pour activer une option de la commande interne shopt : shopt -s option

  • pour désactiver une option de la commande interne shopt : shopt -u option

4.1. Caractères génériques

Les caractères génériques du shell sont : * ? []

Remarque : il ne faut pas confondre la syntaxe [] du méta-langage (cf. Chapitre 1, Introduction à Bash, § 2) et les caractères génériques [] du shell.

Pour que bash interprète les caractères génériques, il est nécessaire que l'option noglob de la commande interne set soit à l'état off.

$ set –o		=> état des différentes options de la commande interne set
allexport      	off
braceexpand    	on
emacs          	on
errexit        	off
errtrace       	off
functrace      	off
hashall        	on
histexpand     	on
history        	on
ignoreeof      	off
interactive-comments	on
keyword        	off
monitor        	on
noclobber      	off
noexec         	off
noglob         	off		=> l'interprétation des caractères génériques est activée
nolog          	off
notify         	off
nounset        	off
onecmd         	off
physical       	off
pipefail       	off
posix          	off
privileged     	off
verbose        	off
vi             	off
xtrace         	off
$

4.1.1. Le caractère *

Le caractère générique * désigne n'importe quelle suite de caractères, même la chaîne vide.

$ echo *
1 _a a A à ami an Arbre e é émirat En état minuit zaza Zoulou
$

Tous les noms d'entrées sont affichés, triés.

$ ls -l a*
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 a 
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 ami 
-rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 an 
$

La notation a* désigne toutes les entrées du répertoire courant dont le nom commence par la lettre a. Par conséquent, dans la commande ls –l a* le shell remplace la chaîne a* par la chaîne : a ami an

En d’autres termes, la commande ls "ne voit pas" le caractère * puisqu’il est prétraité par le shell.

$ echo *a*    => noms des entrées contenant un caractère a
_a a ami an émirat état zaza
$

Ce prétraitement peut être rendu visible en utilisant le mode mise au point du shell à l'aide de la commande set -vx.

$ set –vx		=> passage en mode mise au point
$
$ echo *a*
echo *a*
+ echo _a a ami an émirat état zaza		=> prétraitement puis exécution
_a a ami an émirat état zaza
$ set +vx		=> sortie du mode mise au point
set +vx
+ set +vx
$

Remarques :

  • quand aucune entrée ne correspond au modèle fourni, les caractères et expressions génériques ne sont pas interprétés (cf. §3 de ce chapitre, option nullglob de la commande interne shopt).

    $ echo Z*t
    Z*t
    $
    
  • le caractère . qui débute le nom des fichiers cachés (ex : .profile) ou de répertoires (ex : ..) ainsi que le caractère / doivent être explicitement mentionnés dans les modèles (cf. §3 de ce chapitre, option dotglob de la commande interne shopt).

    $ pwd
    /home/sanchis
    $ echo .pr*  ../../bi*
    .profile ../../bin
    $
    

4.1.2. Le caractère ?

Le caractère générique ? désigne un et un seul caractère.

$ echo ?    => noms d’entrées composés d’un seul caractère
1 a A à e é
$
$ echo ?n
an En
$

Plusieurs caractères génériques différents peuvent être présents dans un modèle.

$ echo ?mi*
ami émirat
$

4.1.3. Les caractères []

Les caractères génériques [] désignent un seul caractère parmi un groupe de caractères.

Ce groupe est précisé entre les caractères []. Il peut prendre deux formes : la forme ensemble et la forme intervalle.

  • Forme ensemble : tous les caractères souhaités sont explicitement mentionnés entre [].

    Le modèle [ame] désigne tous les noms d'entrées constitués d'un seul caractère a, m ou e.

    $ ls -l [ame]
    -rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:17 a
    -rw-r--r-- 1 sanchis sanchis 0  6 janv. 18:18 e
    $
    $ echo ?[ame]*
    _a ami émirat zaza
    $
    

  • Forme intervalle : seules les bornes de l'intervalle sont précisées et séparées par un -.

    $ echo *
    1 _a a A à ami an Arbre e é émirat En état minuit zaza Zoulou
    $
    $ echo [a-z]*
    a ami an e minuit zaza
    $ 
    $ echo [A-Z]*
    A Arbre En Zoulou
    $
    

    L’utilisation du modèle [a-z] est dangereuse car l'interprétation de ce modèle est conditionnée par la valeur des paramètres régionaux et par l'option globasciiranges de la commande interne shopt.

    $ shopt globasciiranges	 	=> affiche l’état de l’option globasciiranges
    globasciiranges	on
    $ 
    $ echo [a-z]*
    a ami an e minuit zaza					(a)
    $ 
    $ shopt -u globasciiranges	=> positionne à off l’option globasciiranges
    $
    $ shopt globasciiranges
    globasciiranges	off
    $ 
    $ echo [a-z]*
    a A à ami an Arbre e é émirat En état minuit zaza	(b)
    $
    

    On s'aperçoit que les listes (a) et (b) sont très différentes. Cette syntaxe est donc non portable car elle dépend de la configuration du système. Il est par conséquent fortement déconseillé de l’employer car elle peut avoir des effets dévastateurs lorsqu’elle est utilisée avec la commande unix rm.

    Si l'on souhaite désigner une classe de caractères tels que les minuscules ou les majuscules, il est préférable d'utiliser la syntaxe POSIX 1003.2 correspondante. Ce standard définit des classes de caractères sous la forme [:nom_classe:].

    Des exemples de classes de caractères définies dans ce standard sont :

    [:upper:] (majuscules)

    [:lower:] (minuscules)

    [:digit:] (chiffres, 0 à 9)

    [:alnum:] (caractères alphanumériques).

    Attention : pour désigner n'importe quel caractère d'une classe, par exemple les minuscules, on place la classe entre les caractères génériques [].

    $ echo [[:lower:]]    => noms d'entrées constitués d'une seule minuscule
    a à e é
    $
    

    Si l’on oublie de placer le nom de la classe entre les caractères génériques [], ce sont les caractères [] du nom de la classe qui seront interprétés par le shell comme caractères génériques.

    $ echo [:lower:]		=> seule l'entrée e correspond à ce modèle
    e
    $
    

    Pour afficher les noms d'entrées commençant par une majuscule.

    $ echo [[:upper:]]*
    A Arbre En Zoulou
    $
    

    Pour afficher les noms d'entrées commençant par une majuscule ou le caractère a :

    $ echo [[:upper:]a]*
    a A ami an Arbre En Zoulou
    $
    

    Il est possible de mentionner un caractère ne devant pas figurer dans un groupe de caractères. Il suffit de placer le caractère ! juste après le caractère [.

    $ echo ?[!n]*    => noms d'entrées ne comportant pas le caractère n en 2ème position
    _a ami Arbre émirat état minuit zaza Zoulou
    $
    $ echo [![:lower:]]
    1 A
    $
    $ echo [![:upper:]]*
    1 _a a à ami an e é émirat état minuit zaza
    $
    $ echo [![:upper:]]*[!at]
    ami an
    $