Il est très facile à utiliser split()
en JavaScript pour diviser une chaîne en un tableau.
Et le script shell?
Dis que je veux faire ceci:
$ script.sh var1_var2_var3
Lorsque l'utilisateur donne une telle chaîne var1_var2_var3
au script.sh, à l'intérieur du script, il convertira la chaîne en un tableau comme
array=( var1 var2 var3 )
for name in ${array[@]}; do
# some code
done
shell
shell-script
string
AGamePlayer
la source
la source
shell
- ce que vous utilisez, avecbash
vous pouvez faireIFS='_' read -a array <<< "${string}"
perl
peut le faire aussi. Ce n'est pas un shell "pur", mais c'est assez courant.Réponses:
Les shells de type Bourne / POSIX ont un opérateur split + glob et il est invoqué chaque fois que vous laissez une expansion de paramètre (
$var
,$-
...), une substitution de commande ($(...)
) ou une expansion arithmétique ($((...))
) sans guillemets dans le contexte d'une liste.En fait, vous l'avez invoqué par erreur lorsque vous l'avez fait à la
for name in ${array[@]}
place defor name in "${array[@]}"
. (En fait, vous devez être conscient que l' invocation de cet opérateur par erreur est source de nombreux bugs et failles de sécurité ).Cet opérateur est configuré avec le
$IFS
paramètre spécial (pour indiquer sur quels caractères se diviser (mais attention à ce que l'espace, la tabulation et la nouvelle ligne y reçoivent un traitement spécial)) et l'-f
option pour désactiver (set -f
) ou activer (set +f
) laglob
partie.Notez également que si
S
in$IFS
était à l'origine (dans le shell Bourne d'où$IFS
vient) pour Separator, dans les shells POSIX, les caractères dans$IFS
devraient plutôt être considérés comme des délimiteurs ou des terminateurs (voir ci-dessous pour un exemple).Donc, pour partager
_
:Pour voir la distinction entre séparateur et délimiteur , essayez:
Cela le divisera en
var1
etvar2
seulement (pas d'élément vide supplémentaire).Donc, pour le rendre similaire à JavaScript
split()
, vous auriez besoin d'une étape supplémentaire:(notez qu'il diviserait un élément vide
$string
en 1 (et non 0 ), comme JavaScriptsplit()
).Pour voir l'onglet des traitements spéciaux, l'espace et la nouvelle ligne reçoivent, comparez:
(où vous obtenez
var1
etvar2
) avecoù vous obtenez:
''
,var1
,''
,var2
,''
.Notez que le
zsh
shell n'invoque pas cet opérateur split + glob implicitement comme ça sauf danssh
ou enksh
émulation. Là, vous devez l'invoquer explicitement.$=string
pour la partie scindée,$~string
pour la partie glob ($=~string
pour les deux), et il a également un opérateur de scission où vous pouvez spécifier le séparateur:ou pour conserver les éléments vides:
Notez qu'il existe
s
pour le fractionnement , pas la délimitation (également avec$IFS
, une non-conformité POSIX connue dezsh
). Il est différent de JavaScriptsplit()
en ce sens qu'une chaîne vide est divisée en élément 0 (et non 1).Une différence notable avec
$IFS
-splitting est que${(s:abc:)string}
se divise sur laabc
chaîne, tandis qu'avecIFS=abc
, cela se diviserait sura
,b
ouc
.Avec
zsh
etksh93
, le traitement spécial que l'espace, la tabulation ou la nouvelle ligne reçoit peut être supprimé en les doublant$IFS
.Comme note historique, le shell Bourne (l'ancêtre ou les shell POSIX modernes) a toujours dépouillé les éléments vides. Il avait également un certain nombre de bogues liés au fractionnement et à l'expansion de $ @ avec des valeurs non par défaut de
$IFS
. Par exempleIFS=_; set -f; set -- $@
, ne serait pas équivalent àIFS=_; set -f; set -- $1 $2 $3...
.Fractionnement sur regexps
Maintenant, pour quelque chose de plus proche de JavaScript
split()
qui peut se diviser en expressions régulières, vous devez vous fier à des utilitaires externes.Dans la boîte à outils POSIX,
awk
possède unsplit
opérateur qui peut se diviser en expressions régulières étendues (ce sont plus ou moins un sous-ensemble des expressions régulières de type Perl prises en charge par JavaScript).Le
zsh
shell a un support intégré pour les expressions régulières compatibles Perl (dans sonzsh/pcre
module), mais l'utiliser pour diviser une chaîne, bien que possible, est relativement lourd.la source
$PATH
sur:
) au contraire, vous voulez généralement conserver des éléments vides. Notez que dans le shell Bourne, tous les personnages recevaient le traitement spécial,ksh
changé cela pour que seuls les blancs (seulement l'espace, la tabulation et la nouvelle ligne) soient traités spécialement.zsh
traitement avec une chaîne contenant 2 caractères ou plus${(s:string:)var}
? Si ajouté, je peux supprimer ma réponse :)S
sigle pour Séparateur , pas délimiteur . C'est du moins ce que dit le manuel de mon bash.$IFS
vient du shell Bourne où il était séparateur , ksh a changé le comportement sans changer le nom. Je mentionne cela pour souligner quesplit+glob
(sauf en zsh ou pdksh) ne se divise plus simplement.Oui, utilisez-le
IFS
et réglez-le sur_
. Ensuite, utilisezread -a
pour stocker dans un tableau (-r
désactive l'expansion de la barre oblique inverse). Notez que ceci est spécifique à bash; ksh et zsh ont des fonctionnalités similaires avec une syntaxe légèrement différente, et plain sh n'a pas du tout de variables de tableau.De
man bash
:Notez que cela
read
s'arrête à la première nouvelle ligne. Passez-d ''
àread
pour éviter cela, mais dans ce cas, il y aura une nouvelle ligne supplémentaire à la fin en raison de l'<<<
opérateur. Vous pouvez le supprimer manuellement:la source
$r
qu'il ne contient pas de caractères de nouvelle ligne ni de barres obliques inverses. Notez également que cela ne fonctionnera que dans les versions récentes dubash
shell.bash
, aread -a
été introduit dans bash 4, non?<<<
n'a été ajouté que récemment,bash
mais il semble qu'il existe depuis 2.05b (2002).read -a
est encore plus vieux que ça.<<<
provientzsh
et est également supporté parksh93
(et mksh et yash) maisread -a
est spécifique à bash (il est-A
en ksh93, yash et zsh).