Bash
Fractionnement de mots
Recherche…
Syntaxe
- Définissez IFS sur newline: IFS = $ '\ n'
- Définissez IFS sur nullstring: IFS =
- Définissez IFS sur / character: IFS = /
Paramètres
Paramètre | Détails |
---|---|
IFS | Séparateur de champ interne |
-X | Les commandes d'impression et leurs arguments au fur et à mesure de leur exécution (option Shell) |
Remarques
- Le fractionnement de mots n'est pas effectué pendant les affectations, par exemple
newvar=$var
- Le fractionnement de mots n'est pas effectué dans la construction
[[ ... ]]
- Utilisez des guillemets doubles sur les variables pour empêcher le fractionnement des mots
Fractionnement avec IFS
Pour être plus clair, créons un script nommé showarg
:
#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo
Voyons maintenant les différences:
$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
est divisé en 4 arguments.IFS
est un espace blanc et le fractionnement des mots se produit donc dans les espaces
$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>
Dans ce qui précède, le fractionnement des mots n'a pas eu lieu car les caractères
IFS
n'ont pas été trouvés.
Maintenant, définissons IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
Le
$var
divise en 4 arguments pas un seul argument.
Quoi, quand et pourquoi
Lorsque le shell effectue une expansion des paramètres , une substitution de commande , une expansion variable ou arithmétique , il recherche les limites de mots dans le résultat. Si une limite de mot est trouvée, le résultat est divisé en plusieurs mots à cette position. La limite du mot est définie par une variable shell IFS
(Internal Field Separator). La valeur par défaut pour IFS est l'espace, la tabulation et la nouvelle ligne, c'est-à-dire que le fractionnement des mots se produira sur ces trois caractères d'espace blanc si cela n'est pas empêché explicitement.
set -x
var='I am
a
multiline string'
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
Dans l'exemple ci-dessus, c'est ainsi que la fonction fun
est exécutée:
fun I am a multiline string
$var
est divisé en 5 arguments, seulsI
,am
eta
seront imprimés.
IFS et fractionnement de mots
Voir quoi, quand et pourquoi si vous ne connaissez pas l'affiliation d'IFS au fractionnement de mots
définissons l'IFS sur un caractère d'espace uniquement:
set -x
var='I am
a
multiline string'
IFS=' '
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
Ce fractionnement ne fonctionnera que sur les espaces. La fonction fun
sera exécutée comme ceci:
fun I 'am
a
multiline' string
$var
est divisé en 3 arguments.I
am\na\nmultiline
et lastring
sera imprimée
Définissons l'IFS sur newline uniquement:
IFS=$'\n'
...
Maintenant, le fun
sera exécuté comme:
fun 'I am' a 'multiline string'
$var
est divisé en 3 arguments.I am
,a
multiline string
sera imprimée
Voyons ce qui se passe si nous définissons IFS sur nullstring:
IFS=
...
Cette fois, le fun
sera exécuté comme ceci:
fun 'I am
a
multiline string'
$var
n'est pas divisé, c'est-à-dire qu'il reste un seul argument.
Vous pouvez empêcher le fractionnement de mots en définissant l'IFS sur nullstring
Une manière générale d'empêcher le fractionnement des mots est d'utiliser un double guillemet:
fun "$var"
empêchera le fractionnement des mots dans tous les cas décrits ci-dessus, c’est-à-dire que la fonction fun
sera exécutée avec un seul argument.
Mauvais effets du fractionnement de mots
$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = $a ]
été interprété comme[ I am a string with spaces = I am a string with spaces ]
.[
est la commande detest
pour laquelleI am a string with spaces
n'est pas un seul argument, c'est plutôt 6 arguments !!
$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = something ]
été interprété comme[ I am a string with spaces = something ]
$ [ $(grep . file) = 'something' ]
bash: [: too many arguments
La commande
grep
renvoie une chaîne multiligne avec des espaces, vous pouvez donc imaginer combien d’arguments sont disponibles: D
Voir quoi, quand et pourquoi pour l'essentiel.
Utilité du fractionnement de mots
Dans certains cas, le fractionnement des mots peut être utile:
Remplissage du tableau:
arr=($(grep -o '[0-9]\+' file))
Cela remplira
arr
avec toutes les valeurs numériques trouvées dans le fichier
En boucle à travers des mots séparés par des espaces:
words='foo bar baz'
for w in $words;do
echo "W: $w"
done
Sortie:
W: foo
W: bar
W: baz
Paramètres séparés par des espaces qui ne contiennent pas d'espaces blancs:
packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs
ou
packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs
Cela va installer les paquets. Si vous doublez les
$packs
cela générera une erreur.
Unquoetd
$packs
envoie tous les noms de paquets séparés par des espaces comme arguments àapt-get
, en les citant, il enverra la chaîne$packs
en un seul argument, puisapt-get
tentera d'installer un paquet nomméapache2 php php-mbstring php-mysql
(pour le premier) qui n'existe évidemment pas
Voir quoi, quand et pourquoi pour l'essentiel.
Fractionnement par séparateur
Nous pouvons simplement effectuer un remplacement simple des séparateurs de l'espace vers la nouvelle ligne, comme dans l'exemple suivant.
echo $sentence | tr " " "\n"
Il divisera la valeur de la sentence
variable et la montrera ligne par ligne respectivement.