Le moyen probablement le plus simple et le plus sûr dans BASH 3 et supérieur est:
var="string to split"
read -ra arr <<<"$var"
(où arr
est le tableau qui prend les parties fractionnées de la chaîne) ou, s'il peut y avoir des sauts de ligne dans l'entrée et que vous voulez plus que la première ligne:
var="string to split"
read -ra arr -d '' <<<"$var"
(veuillez noter l'espace dans -d ''
, il ne peut pas être laissé de côté), mais cela pourrait vous donner une nouvelle ligne inattendue de <<<"$var"
(car cela ajoute implicitement un LF à la fin).
Exemple:
touch NOPE
var="* a *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done
Produit les résultats attendus
[*]
[a]
[*]
car cette solution (contrairement à toutes les solutions précédentes ici) n'est pas sujette à un globbing shell inattendu et souvent incontrôlable.
Cela vous donne également la pleine puissance d'IFS comme vous le souhaitez probablement:
Exemple:
IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done
Produit quelque chose comme:
[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]
Comme vous pouvez le voir, les espaces peuvent également être préservés de cette façon:
IFS=: read -ra arr <<<' split : this '
for a in "${arr[@]}"; do echo "[$a]"; done
les sorties
[ split ]
[ this ]
Veuillez noter que la gestion de IFS
BASH est un sujet en soi, alors faites vos tests, quelques sujets intéressants à ce sujet:
unset IFS
: Ignore les exécutions de SPC, TAB, NL et commence et se termine en ligne
IFS=''
: Pas de séparation de champ, lit tout
IFS=' '
: Exécutions de SPC (et SPC uniquement)
Un dernier exemple
var=$'\n\nthis is\n\n\na test\n\n'
IFS=$'\n' read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done
les sorties
1 [this is]
2 [a test]
tandis que
unset IFS
var=$'\n\nthis is\n\n\na test\n\n'
read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done
les sorties
1 [this]
2 [is]
3 [a]
4 [test]
BTW:
Si vous n'avez pas l'habitude de $'ANSI-ESCAPED-STRING'
vous y habituer, c'est un gain de temps.
Si vous n'incluez pas -r
(comme dans read -a arr <<<"$var"
), alors read n'échappe pas à la barre oblique inverse. Ceci est laissé comme exercice pour le lecteur.
Pour la deuxième question:
Pour tester quelque chose dans une chaîne, je m'en tiens habituellement case
, car cela peut vérifier plusieurs cas à la fois (remarque: la casse n'exécute que la première correspondance, si vous avez besoin d'utiliser des case
instructions de multiplication ), et ce besoin est assez souvent le cas (pun prévu):
case "$var" in
'') empty_var;; # variable is empty
*' '*) have_space "$var";; # have SPC
*[[:space:]]*) have_whitespace "$var";; # have whitespaces like TAB
*[^-+.,A-Za-z0-9]*) have_nonalnum "$var";; # non-alphanum-chars found
*[-+.,]*) have_punctuation "$var";; # some punctuation chars found
*) default_case "$var";; # if all above does not match
esac
Vous pouvez donc définir la valeur de retour pour vérifier le SPC comme ceci:
case "$var" in (*' '*) true;; (*) false;; esac
Pourquoi case
? Parce qu'il est généralement un peu plus lisible que les séquences d'expression régulière, et grâce aux métacaractères Shell, il gère très bien 99% de tous les besoins.