Supposons que j'ai une variable shell Unix comme ci-dessous
variable=abc,def,ghij
Je veux extraire toutes les valeurs (abc
, def
et ghij
) en utilisant une boucle for et passer chaque valeur à une procédure.
Le script doit permettre d'extraire un nombre arbitraire de valeurs séparées par des virgules à partir de $variable
.
Vous pouvez utiliser le script suivant pour parcourir dynamiquement votre variable, quel que soit le nombre de champs dont elle dispose, à condition qu'elle soit uniquement séparée par des virgules.
variable=abc,def,ghij
for i in $(echo $variable | sed "s/,/ /g")
do
# call your procedure/other scripts here below
echo "$i"
done
Au lieu de l'appel echo "$i"
ci-dessus, entre les do
et done
dans la boucle for, vous pouvez appeler votre procédure proc "$i"
.
Update : L'extrait ci-dessus fonctionne si la valeur de variable ne contient pas d'espaces. Si vous avez une telle exigence, veuillez utiliser l’une des solutions susceptibles de changer IFS
puis d’analyser votre variable.
J'espère que cela t'aides.
Ne pas jouer avec IFS
N'appelle pas de commande externe
variable=abc,def,ghij
for i in ${variable//,/ }
do
# call your procedure/other scripts here below
echo "$i"
done
Utilisation de bash string manipulation http://www.tldp.org/LDP/abs/html/string-manipulation.html
Si vous définissez un séparateur de champ différent, vous pouvez directement utiliser une boucle for
:
IFS=","
for v in $variable
do
# things with "$v" ...
done
Vous pouvez également stocker les valeurs dans un tableau, puis le parcourir comme indiqué dans Comment fractionner une chaîne dans un délimiteur dans Bash? :
IFS=, read -ra values <<< "$variable"
for v in "${values[@]}"
do
# things with "$v"
done
$ variable="abc,def,ghij"
$ IFS=","
$ for v in $variable
> do
> echo "var is $v"
> done
var is abc
var is def
var is ghij
Vous pouvez trouver une approche plus large dans cette solution pour Comment parcourir une liste séparée par des virgules et exécuter une commande pour chaque entrée .
Exemples sur la seconde approche:
$ IFS=, read -ra vals <<< "abc,def,ghij"
$ printf "%s\n" "${vals[@]}"
abc
def
ghij
$ for v in "${vals[@]}"; do echo "$v --"; done
abc --
def --
ghij --
#/bin/bash
TESTSTR="abc,def,ghij"
for i in $(echo $TESTSTR | tr ',' '\n')
do
echo $i
done
Je préfère utiliser tr au lieu de sed, parce qu’il a des problèmes avec les caractères spéciaux comme\r\n dans certains cas.
une autre solution consiste à définir IFS sur certains séparateurs
Une autre solution n'utilisant pas IFS tout en préservant les espaces:
$ var="a bc,def,ghij"
$ while read line; do echo line="$line"; done < <(echo "$var" | tr ',' '\n')
line=a bc
line=def
line=ghij
Essaye celui-là.
#/bin/bash
testpid="abc,def,ghij"
count=`echo $testpid | grep -o ',' | wc -l` # this is not a good way
count=`expr $count + 1`
while [ $count -gt 0 ] ; do
echo $testpid | cut -d ',' -f $i
count=`expr $count - 1 `
done
Voici une solution alternative basée sur le tr n'utilisant pas d'écho, exprimée sous la forme d'une ligne.
for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done
Je me sens mieux sans écho, mais ce n’est que ma préférence personnelle.