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, seuls I , am et a 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 la string 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 de test pour laquelle I 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, puis apt-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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow