Compatible répondre
Pour cela DONC, la question, il y a déjà beaucoup de différentes façon de le faire en bash.
Mais bash autant de spécial , donc appelé bashism qui fonctionnent bien, mais qui ne fonctionne pas dans tout autre shell.
En particulier, les tableaux, tableau associatif, et le modèle de substitution sont de la pure bashisms et peuvent ne pas fonctionner sous d'autres coquilles.
Sur ma Debian GNU/Linux, il existe un standard shell appelé dash, mais je connais beaucoup de gens qui aiment utiliser ksh.
Enfin, dans de très petites la situation, il existe un outil spécial appelé busybox avec son propre shell interprète (ash).
Chaîne demandée
La chaîne de l'échantillon dans la question, c'est:
IN="bla@some.com;john@home.com"
Cela pourrait être utile avec des espaces et des espaces pourrait modifier le résultat de la routine, je préfère utiliser cet exemple de chaîne:
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
Scinde une chaîne basée sur délimiteur dans bash (version >=4.2)
En vertu de pur bash, on peut utiliser des tableaux et des IFS:
var="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
oIFS="$IFS"
IFS=";"
declare -a fields=($var)
IFS="$oIFS"
unset oIFS
IFS=\; read -a fields <<<"$var"
En utilisant cette syntaxe cadre de la récente bash ne pas changer l' $IFS
pour la session en cours, mais uniquement pour la commande en cours:
set | grep ^IFS=
IFS=$' \t\n'
Maintenant, la chaîne var
est découpé et stockées dans un tableau (nommé en fields
):
set | grep ^fields=\\\|^var=
fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>")
var='bla@some.com;john@home.com;Full Name <fulnam@other.org>'
C'est le quickiest façon de le faire car il n'y a pas de fourches et aucune ressource externe appelé.
À partir de là, vous pouvez utiliser la syntaxe que vous connaissez déjà pour le traitement de chaque domaine;
for x in "${fields[@]}";do
echo "> [$x]"
done
> [bla@some.com]
> [john@home.com]
> [Full Name <fulnam@other.org>]
ou une goutte de chaque champ après le traitement (j'aime ce décalage approche):
while [ "$fields" ] ;do
echo "> [$fields]"
fields=("${fields[@]:1}")
done
> [bla@some.com]
> [john@home.com]
> [Full Name <fulnam@other.org>]
ou même pour une simple impression (plus courte syntaxe):
printf "> [%s]\n" "${fields[@]}"
> [bla@some.com]
> [john@home.com]
> [Full Name <fulnam@other.org>]
Scinde une chaîne basée sur délimiteur dans le shell
Mais si vous écrivez quelque chose d'utilisable dans de nombreuses coquilles, vous devez ne pas utiliser bashisms.
Il y a une syntaxe, utilisé dans de nombreuses coquilles, pour scinder une chaîne accros de la première ou de la dernière occurence d'une chaîne:
${var#*SubStr} # will drop begin of string upto first occur of `SubStr`
${var##*SubStr} # will drop begin of string upto last occur of `SubStr`
${var%SubStr*} # will drop part of string from last occur of `SubStr` to the end
${var%%SubStr*} # will drop part of string from first occur of `SubStr` to the end
( Le manque de c'est la principale raison de ma réponse à la publication ;)
Ce petit exemple de script fonctionne bien sous bash, dash, ksh, busybox et a été testé sous Mac-OS bash:
var="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
while [ "$var" ] ;do
iter=${var%%;*}
echo "> [$iter]"
[ "$var" = "$iter" ] && \
var='' || \
var="${var#*;}"
done
> [bla@some.com]
> [john@home.com]
> [Full Name <fulnam@other.org>]
Amusez-vous!