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>
$varest divisé en 4 arguments.IFSest 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
IFSn'ont pas été trouvés.
Maintenant, définissons IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
Le
$vardivise 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
$varest divisé en 5 arguments, seulsI,ametaseront 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
$varest divisé en 3 arguments.Iam\na\nmultilineet lastringsera imprimée
Définissons l'IFS sur newline uniquement:
IFS=$'\n'
...
Maintenant, le fun sera exécuté comme:
fun 'I am' a 'multiline string'
$varest divisé en 3 arguments.I am,amultiline stringsera 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'
$varn'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 detestpour laquelleI am a string with spacesn'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
greprenvoie 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
arravec 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
$packscela générera une erreur.
Unquoetd
$packsenvoie tous les noms de paquets séparés par des espaces comme arguments àapt-get, en les citant, il enverra la chaîne$packsen un seul argument, puisapt-gettentera 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.