======Bash : les caractères de transformation de parametres======
* Objet : suite de la série de wiki visant à maîtriser bash via les différents caractère spéciaux.
* Niveau requis : {{tag>débutant avisé}}
* Commentaires : FIXME
* Débutant, à savoir : [[:doc:systeme:commandes:le_debianiste_qui_papillonne|Utiliser GNU/Linux en ligne de commande, tout commence là !.]] :-)
* Suivi :
* Création par [[user>Hypathie]] le 08/04/2014
* Testé par [[user>Hypathie]] en Avril 2014
* Commentaires sur le forum : [[https://debian-facile.org/viewtopic.php?pid=140921#p140921 | ici]] ((N'hésitez pas à y faire part de vos remarques, succès, améliorations ou échecs !))
**Nota :** Contributeurs, les FIXME sont là pour vous aider, supprimez-les une fois le problème corrigé ou le champ rempli !
* [[doc:programmation:shells:bash-les-differents-caracteres-speciaux|Vision d'ensemble]]
* [[doc:programmation:shells:la-page-man-bash-les-caracteres-speciaux|Détail et caractères]]
* [[doc:programmation:shells:la-page-man-bash-ii-les-operateurs-lexicographiques|Les opérateurs lexicographiques]]
* [[doc:programmation:shells:page-man-bash-iii-les-operateurs-de-comparaison-numerique|Les opérateurs de comparaison numérique]]
* [[doc:programmation:shells:page-man-bash-iv-symboles-dans-les-calculs-mathematiques|Les symboles dans les calculs]]
* [[doc:programmation:shells:page-man-bash-v-les-tableaux|Les tableaux]]
* ;-)
* [[doc:programmation:shells:bash-vii-globs-etendus-regex|Bash : Variables, globs étendus, ERb, ERe]]
**Nota : Dans cette page l'expression "caractère générique" est employée dans le sens de métacaractère, glob ou pattern(([[doc:programmation:shells:bash-les-differents-caracteres-speciaux#definition-usuelle-de-metacaractere-et-detail]])).**
=====Caractères et syntaxe de transformation de paramètres=====
On peut substituer des variables ou paramètres définis(es) précédemment par l'utilisateur dans un script, et cela permet d'en transformer le contenu. Cela permet aussi de donner une valeur à une variable déclarée mais nulle.
^Syntaxe de substitution ^Significations ^
|'' ${!nom-paramètre} ''\\ (ne pas confondre avec l'appel de l'historique ''!'', ou le ''!='' des tests) |Remplace la valeur d'un paramètre |
|'' ${paramètre:-motif} '' |Utilisation d'une valeur par défaut |
|'' ${paramètre:=motif} '' |Attribution d'une valeur par défaut |
|'' ${paramètre:début:longueur}'' |Extraction de sous-chaîne |
|'' ${paramètre:+motif} '' |Utilisation d'une valeur différente |
|'' ${paramètre:?motif} '' |Affichage d'erreur si paramètre inexistant |
|'' ${#paramètre} '' |Remplace un paramètre précédent par sa longueur en caractères |
|'' ${paramètre##motif} '' |Supprime de $paramètre la plus longue partie de $motif qui correspond au début de $paramètre |
|'' ${paramètre#motif} '' |Supprime à partir de $paramètre la plus courte partie de $motif qui correspond au début de $paramètre. |
|'' ${paramètre%%motif} '' |Supprime de ''$paramètre'' la plus grande partie de $motif qui corresponde à la fin de $paramètre. |
|'' ${paramètre%motif} '' |Supprime de $paramètre la plus petite partie de $motif correspondant à la fin de $paramètre. |
|'' ${paramètre//motif/chaîne} '' |Remplace motif par chaîne pour transformer "paramètre"|
====Exemples sans caractères génériques (=pattern-less)====
Certaines substitutions de paramètre recoupent les fonctionnalités de la commande expr.\\
#!/bin/bash
#!/bin/bash
chaine=abcABC123
echo ${#chaine}
echo `expr "$chaine" : '.*'`
9
9
l'opérateur : est équivalent à un match (voir expressions rationnelles) et commande "expr"
===Substitution de paramètres par référence indirecte===
#!/bin/bash
set -o posix
tante=tati
tati=tata
echo "tante = $tante" #référence directe (rappel)
echo "tante = ${!tante}" #référence indirecte
tante = tati
tante = tata
===Substitution par modification===
#!/bin/bash
set -o posix
var=ancienne-valeur
echo ${var:+nouvelle-valeur}
nouvelle-valeur
===Substitution d'un paramètre non-déclaré ou de valeur nulle===
#!/bin/bash
set -o posix
#vi=
echo ${vi-`whereis vi`}
vi=
echo ${vi:-`whereis vi`}
vi: /usr/bin/vi /usr/bin/X11/vi /usr/share/man/man1/vi.1posix.gz /usr/share/man/man1/vi.1.gz
vi: /usr/bin/vi /usr/bin/X11/vi /usr/share/man/man1/vi.1posix.gz /usr/share/man/man1/vi.1.gz
===Attribution d'une valeur par défaut===
#!/bin/bash
echo ${nom_utilasateur=`whoami`} # attribution d'une valeur par défaut, rien n'a été déclaré
nom_utilisateur=moi # déclaré et non-nul
echo ${nom_utilisateur:=`whoami`}
hypathie
moi
* Ou encore :
Attention : l'indice du premier caractère d'une chaîne de caractères est 0.
#!/bin/bash
echo "J'aime les chats"
surdite="j\' aime les Chats" # Les caractères antislash, apostrophe et espace comptent pour un caractère aussi.
echo "T' aimes qui ? "
echo ${surdite:8} # le 8ième à partir de 0 est inclus
J'aime les chats
T' aimes qui ?
les Chats
===Extraction de sous-chaîne contenu dans la valeur de la variable ${paramètre:début:longueur}===
#!/bin/bash
set -o posix
echo "abcdefghijklmnopqrstu : extraire le plus long mot possible : "
devinette=abcdefghijklmnopqrstu
echo -n ${devinette:0:1} ; echo -n ${devinette:13:1} ; echo -n ${devinette:19:1} ;
echo -n ${devinette:8:1} ; echo -n ${devinette:2:1} ; echo -n ${devinette:14:1} ;
echo -n ${devinette:13:1} ; echo -n ${devinette:18:1} ; echo -n ${devinette:19:1}
echo -n ${devinette:8:1} ; echo -n ${devinette:19:1} ; echo -n ${devinette:20:1}
echo -n ${devinette:19:1} ; echo -n ${devinette:8:1} ; echo -n ${devinette:14:1}
echo -n ${devinette:13:1} ; echo -n ${devinette:13:1} ; echo -n ${devinette:4:1}
echo -n ${devinette:11:1} ; echo -n ${devinette:11:1} ; echo -n ${devinette:4:1}
echo -n ${devinette:12:1} ; echo -n ${devinette:4:1} ; echo -n ${devinette:13:1}
echo ${devinette:19:1}
echo "extraire trois lettres à partir de la lettre f : "
echo ${devinette:5:3} # f est la sixième mais 5 car la première est pointée zéro, on en prends 3.
echo "extraire les trois premières lettres"
set abcdefgh
echo ${1:0:3} # 1 car avec set il s'agit de valeur de paramètre donc pas nom,
# 0 pointe la première lettre, et on en prend 3.
abcdefghijklmnopqrstu : extraire le plus long mot possible :
anticonstitutionnellement
extraire trois lettres à partir de la lettre f :
fgh
extraire les trois premières lettres
abc
===Substitution de la valeur d'une variable (ou d'un paramètre) par la longueur de sa chaîne ${#paramètre}===
#!/bin/bash
set -o posix
mot="anticonstitutionnellement"
echo ${#mot}
set anticonstitutionnellement
echo ${#1} #rappelons-nous du 1 dans ${1:0:3}
25
25
===Suppression de la plus courte chaîne ${paramètre#modèle}===
#!/bin/bash
set -o posix
mot=pingpong
echo ${mot#ping}
pong
===Suppression de la plus longue chaîne $paramètre##modèle}===
#!/bin/bash
set -o posix
mot=fichier.txt
echo ${mot##fichier}
.txt
===Modifier un paramètre en supprimant ses derniers caractères===
#!/bin/bash
set -o posix
var=fichier.txt
echo ${var%%.txt}
fichier
* Ou encore :
#!/bin/bash
set -o posix
var1=abc.fichier
echo ${var1%.fichier}
abc
===Remplacer une partie d'une chaîne par un motif littéral ===
Toutes les occurrences du motif sont remplacées par la chaîne.
#!/bin/bash
set -o posix
var1=chienchien
echo ${var1//ien/at}
var2=viaouviaou
echo ${var2//v/m}
chatchat
miaoumiaou
* Remarque : ne changer que la première occurrence.
echo ${var/a/x}
var1=fichier.txt
echo ${var1/txt/sh}
xbcabc
fichier.sh
* Quand il s'agit de ne changer que la première occurrence, on peut choisir de changer la première ou la dernière :
#!/bin/bash
set -o posix
var=blablabla
echo ${var/#bla/bli}
var=blablabla
echo ${var/%bla/bli}
bliblabla
blablabli
* Pour supprimer un groupe de caractère :
${paramètre//motif/}
> permet de remplacer par rien toutes les occurrences du motif
${paramètre/motif/}
> permet de remplacer par rien la première occurrence du motif à l'intérieur de paramètre.
* Par exemple :
#!/bin/bash
set -o posix
var=blablabla
echo ${var//bl/}
var=blablabla
echo ${var/bl/}
aaa
ablabla
====Substitution de chaînes en utilisant les globs basiques (patterns ou caractères génériques)====
Tout ce qui a été vu dans les exemples du paragraphe 1 (ci-dessus) peut porter à confusion avec les expressions rationnelles (correspondance, substitution) :
m/motif/ #avec le m facultatif
s/motif/chaîne
Cette confusion vient souvent de la ressemblance de la syntaxe ''var/.../...'' ou ''var//.../...'' que l'on utilise pour la substitution de paramètres, avec celle des expressions rationnelles (voir la note ci-dessous).\\
Elle est renforcée aussi par la ressemblance des globs '' * '', '' ? '', ''[ - ]'' ainsi que par certains caractères utilisés avec les expressions rationnelles .\\
Attention donc, s'il est possible d'utiliser '' * '' , '' ? '' et ''[ - ]'' dans les modifications de chaînes d'un paramètre que nous venons de voir, il n'est pas possible d'utiliser les expressions rationnelles directement.\\
Avec le shell Bash on utilise les //expressions rationnelles// au moyen de commandes externes qui elles les utilisent, comme grep, sed, awk, vi (par exemple : set -o vi).\\
Voir : [[doc:programmation:shells:bash-vii-globs-etendus-regex?#correspondance-de-motifs-avec-les-expressions-rationnelles]].
On n'utilise pas de //ER// pour ce qui concerne les substitutions de paramètres abordés ici, mais il est possible d'utiliser les caractères génériques basiques (pattern ou glob), ainsi que "les génériques de class" [[:class:]] au moyen de sa commande interne "shopt", munie de l'option extglob.
==== Utilisation du caractère génériques " ? ". ====
#!/bin/bash
var=debian123456facile
echo ${var//2?4/.}
var1=debian123456facile
echo ${var1//3?5/.}
var2=debian123456facile
echo ${var2//4?6/.}
var3=debian123456facile
echo ${var3//?/.}
debian1.56facile
debian12.6facile
debian123.facile
..................
==== Utilisation du caractère générique "*". ===
#!/bin/bash
set -o posix
var=debian123456facile
echo ${var//1*6/.}
debian.facile
===Suppression à gauche===
echo $PWD
echo ${PWD#*/}
echo ${PWD##*/}
/home/hypathie
home/hypathie
hypathie
===Suppression à droite===
fichier="ABCD::12:03:2014"
echo ${fichier%:*}
echo ${fichier%%:*}
ABCD::12:03
ABCD
====Utilisation des brackets [ - ] ====
#!/bin/bash
v=debian123456facile
echo ${v//[1-9]/.}
v1=debian123456facile
echo ${v1//[1-9]*/.}
v2=debian123456facile
echo ${v2//[1-9]*/}
v3=debian123456facile
echo ${v3//[1-9]*/.}
v4=debian123456facile
echo ${v4//*[1-9]/.}
v5=debian123456facile
echo ${v5//[a-z]/x}
v6=debian123456facile
echo ${v6//[a-z 0-9]/x}
echo ${v6//[0-9 a-z]/x}
debian......facile
debian.
debian
debian.
.facile
xxxxxx123456xxxxxx
xxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxx
====Modifier la case : caractères {...^...}, {...^^...}, {...,...}, {...,,...}====
#!/bin/bash
var="je vais apprendre à utiliser le shell."
echo ${var^}
echo ${var^}
echo ${var^^[ai]}
var1="JE VAIS APPRENDRE À UTILISER LE SHELL."
echo ${var1,}
echo ${var1,,}
echo ${var1,,e}
echo ${var1,,[AE]}
Je vais apprendre à utiliser le shell.
Je vais apprendre à utiliser le shell.
je vAIs Apprendre à utIlIser le shell.
jE VAIS APPRENDRE À UTILISER LE SHELL.
je vais apprendre À utiliser le shell.
JE VAIS APPRENDRE À UTILISER LE SHELL.
Je VaIS aPPReNDRe À UTILISeR Le SHeLL.
====commande shopt -s extglob et braquet de classe [ [:class:] ]===
([[:lower:]])
Elle désigne une suite de caractères minuscules : on peut retirer la première occurrence, ou toutes les occurrences à des caractères.
#!/bin/bash
shopt -s extglob
var=123abcd45ef
echo ${var/+([[:lower:]])/} #1ière occ. de munisc.
var1=123a45bcdef
echo ${var1/+([[:lower:]])/}
var2=ab123cdefgh45ij
echo ${var2//+([[:lower:]])/} #toutes occ. de minusc.
12345ef
12345bcdef
12345
rappel pour le + des lignes 4, 6, 8\\
${paramètre:+motif} ⇒ utilisation d'une valeur différente
===et d'autres encore :===
([[:digit:]])
Exemples
#!/bin/bash
shopt -s extglob
var1=123abcd456
echo ${var1//+([[:digit:]])/}
var2=ABC123EFG
echo ${var2//+([[:upper:]])/}
var3=abc?ABC\!123.de\;gh\:45,6
echo ${var3//+([[:punct:]])/}
var4="AB c d 1 2 3" #Ne pas oublier les " "
echo ${var4//+([[:space:]])/}
abcd
123
abcABC123degh456
ABcd123
====Négation de caractères [^...] et [!...] ; extraction de symboles [.SYMBOL.]====
#!/bin/bash
shopt -s extglob
var1=123abcd456
echo ${var1//+([^abc])/}
var2=123abcd456
echo ${var2//+([^[:digit:]])/}
var3=12\/3abc@d456
echo ${var3//+([!abcd])/}
var4=123abcd456
echo "On ne remplace par rien donc c'est pareil :
${var4//+([.SYMBOL.])/}"
var5=123abcd456
echo "On remplace par l'inverse de ce qu'il n'y a pas :
c'est-à-dire par : ${var5//+([^[.SYMBOL.]])/}:"
var6="ÇSYMBOLa alors !"
echo ${var6//+([.SYMBOL.])/}
abc
123456
abcd
On ne remplace par rien donc c'est pareil :
123abcd456
On remplace par l'inverse de ce qu'il n'y a pas :
c'est-à-dire par : :
Ça alors !
Donc :
* Remarque sur les syntaxes : '' $var/.../... '' et '' $var//.../... ''.
* Attention de ne pas confondre les globs étendus et les expressions régulières
Avec shopt -s extglob :
- On peut utiliser les globs simples ( ''*'' , ''?'' , ''[ ]'' ) et les globs étendus : ''[ ]'', ''|'', ''?'', ''@'', ''!'', ''+'', '' ^ ''
- Mais on ne peut pas utiliser les expressions régulières (où les globs étendus sont "ré-utilisés" avec une syntaxe différente, à côté d'autres caractères : la distinction entre globs étendus et //ER// est développée [[doc:programmation:shells:bash-vii-globs-etendus-regex|ici]] ).\\
À voir aussi : http://wiki.bash-hackers.org/syntax/pattern\\
* Pour les classes de caractères, attention à la norme POSIX : [[http://hyperpolyglot.org/shell]] :
Non POXIS : ''[[:nom-classe:]]''\\
POSIX : ''[:upper:]'' ; ''[:alnum:]'', etc.
Une liste plus complète ici : [[doc:programmation:shell:regexp#les-ensembles-de-caracteres-possibles]]\\
Voir le wiki suivant : [[doc:programmation:shells:bash-vii-globs-etendus-regex|globs étendus et expressions régulières]]
* Pour les autres options de la commande interne shopt :
Voir man bash (tout à la fin, c'est long 8-o ) au paragraphe "commandes internes".
=====tuto précédent : =====
[[doc:programmation:shells:page-man-bash-v-les-tableaux|Bash : les tableaux]]
=====tuto suivant : =====
[[doc:programmation:shells:bash-vii-globs-etendus-regex|Bash : globs étendus et regex]]