Convertir les arguments de ligne de commande en un tableau dans Bash


162

Comment convertir des arguments de ligne de commande en un tableau de scripts bash?

Je veux prendre ceci:

./something.sh arg1 arg2 arg3

et le convertir en

myArray=( arg1 arg2 arg3 )

afin que je puisse utiliser myArray pour une utilisation ultérieure dans le script.

Ce précédent article SO se rapproche, mais n'aborde pas la façon de créer un tableau: Comment analyser les arguments de ligne de commande dans Bash?

J'ai besoin de convertir les arguments en un tableau de script bash régulier; Je me rends compte que je pourrais utiliser d'autres langages (Python, par exemple) mais que je dois le faire dans bash. Je suppose que je recherche une fonction "append" ou quelque chose de similaire?

MISE À JOUR: Je voulais également demander comment vérifier zéro argument et attribuer une valeur de tableau par défaut, et grâce à la réponse ci-dessous, j'ai pu faire fonctionner cela:

if [ "$#" -eq 0 ]; then
  myArray=( defaultarg1 defaultarg2 )
else
  myArray=( "$@" )
fi

Réponses:


208

En fait, vos arguments de ligne de commande sont déjà pratiquement comme un tableau. Au moins, vous pouvez traiter la $@variable comme un tableau. Cela dit, vous pouvez le convertir en un tableau réel comme celui-ci:

myArray=( "$@" )

Si vous souhaitez simplement taper des arguments et les insérer dans la $@valeur, utilisez set:

$ set -- apple banana "kiwi fruit"
$ echo "$#"
3
$ echo "$@"
apple banana kiwi fruit

Comprendre comment utiliser la structure des arguments est particulièrement utile dans POSIX sh, qui n'a rien d'autre qu'un tableau.


2
Merci! Fonctionne très bien! Était sur le point de demander comment vérifier zéro argument et attribuer une valeur de tableau par défaut, et le $ # fonctionne parfaitement pour cela!
Suman

1
setvous permet de définir les paramètres de position de l'oscilloscope. Il vous permet également de définir les options du shell. Vous pouvez le faire set foo, ce qui signifie se $1développer en "foo", mais si vos paramètres commencent par un tiret set, vous supposerez que vous voulez définir une option shell. Le double tiret garantit que tous les paramètres suivants sont interprétés comme des paramètres de position à définir.
kojiro

12
One gotcha: echo $@affichera tous les arguments, mais echo $myArrayn'imprimera que le premier élément. Pour les voir tous, utilisez echo ${myArray[@]}.
z0r

4
@ z0r Si vous ne mettez pas de guillemets doubles autour de ces extensions, alors bash les re-divisera et perdra peut-être leur sens.
kojiro

À droite, la manière générale de "splater" un tableau et d'utiliser chaque élément est "${myArray[@]}". Si vous souhaitez parcourir le tableau, vous avez besoin des guillemets pour éviter de diviser ses éléments individuels sur IFS
BallpointBen

66

Peut-être que cela peut aider:

myArray=("$@") 

vous pouvez également parcourir les arguments en omettant 'in':

for arg; do
   echo "$arg"
done

sera équivalent

for arg in "${myArray[@]}"; do
   echo "$arg"
done

3
Questions pour les débutants: Comment bash sait-il quoi mettre dans le argchamp - est-ce une variable prédéfinie? ${var}est étendu au contenu de var. ${var[n]}est étendu au contenu de l'élément ndu tableau var. Est-ce ${var[@]}alors développer le tableau entier, c'est-à-dire ${var[0]} ${var[1]} ... ${var[n]}(avec nl'index du dernier élément)?
Christian du

4
[for] without [in] bouclera sur le tableau d'arguments $ @ ($ 1, $ 2, etc.). Qui peut être défini également avec la commande [set], par exemple set - arg1 arg2
Nahuel Fouilleul

17

En fait, la liste des paramètres est accessible avec $1 $2 ...etc.
Ce qui est exactement équivalent à:

${!i}

Ainsi, la liste des paramètres peut être modifiée avec set,
et ${!i}c'est le bon moyen d'y accéder:

$ set -- aa bb cc dd 55 ff gg hh ii jjj kkk lll
$ for ((i=0;i<=$#;i++)); do echo "$#" "$i" "${!i}"; done
12 1 aa
12 2 bb
12 3 cc
12 4 dd
12 5 55
12 6 ff
12 7 gg
12 8 hh
12 9 ii
12 10 jjj
12 11 kkk
12 12 lll

Pour votre cas spécifique, cela pourrait être utilisé (sans avoir besoin de tableaux), pour définir la liste des arguments quand aucun n'a été donné:

if [ "$#" -eq 0 ]; then
    set -- defaultarg1 defaultarg2
fi

ce qui se traduit par cette expression encore plus simple:

[ "$#" == "0" ] && set -- defaultarg1 defaultarg2

L'exemple d'écho ne devrait-il pas être: echo "$#" "$i+1" "${!i}";pour obtenir la sortie exactement comme indiqué?
Zael

6

Voici une autre utilisation:

#!/bin/bash
array=( "$@" )
arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   echo "${array[$i]}"
done

4

Plus simple encore, vous pouvez opérer directement sur $@;)

Voici comment passer une liste d'arguments directement à partir de l'invite:

function echoarg { for stuff in "$@" ; do echo $stuff ; done ; } 
    echoarg Hey Ho Lets Go
    Hey
    Ho
    Lets
    Go

1
Encore plus facile, for stuff in "$@" ; do ...c'est la même chose que for stuff ; do ...:)
kkm

1

Vue côte à côte de la façon dont le tableau et $ @ sont pratiquement identiques.

Code:

#!/bin/bash

echo "Dollar-1 : $1"
echo "Dollar-2 : $2"
echo "Dollar-3 : $3"
echo "Dollar-AT: $@"
echo ""

myArray=( "$@" )

echo "A Val 0: ${myArray[0]}"
echo "A Val 1: ${myArray[1]}"
echo "A Val 2: ${myArray[2]}"
echo "A All Values: ${myArray[@]}"

Contribution:

./bash-array-practice.sh 1 2 3 4

Production:

Dollar-1 : 1
Dollar-2 : 2
Dollar-3 : 3
Dollar-AT: 1 2 3 4

A Val 0: 1
A Val 1: 2
A Val 2: 3
A All Values: 1 2 3 4

1

L'importance des guillemets doubles mérite d'être soulignée. Supposons qu'un argument contienne des espaces.

Code:

#!/bin/bash
printf 'arguments:%s\n' "$@"
declare -a arrayGOOD=( "$@" )
declare -a arrayBAAD=(  $@  )

printf '\n%s:\n' arrayGOOD
declare -p arrayGOOD
arrayGOODlength=${#arrayGOOD[@]}
for (( i=1; i<${arrayGOODlength}+1; i++ ));
do
   echo "${arrayGOOD[$i-1]}"
done

printf '\n%s:\n' arrayBAAD
declare -p arrayBAAD
arrayBAADlength=${#arrayBAAD[@]}
for (( i=1; i<${arrayBAADlength}+1; i++ ));
do
   echo "${arrayBAAD[$i-1]}"
done

Production:

> ./bash-array-practice.sh 'The dog ate the "flea" -- and ' the mouse.
arguments:The dog ate the "flea" -- and 
arguments:the
arguments:mouse.

arrayGOOD:
declare -a arrayGOOD='([0]="The dog ate the \"flea\" -- and " [1]="the" [2]="mouse.")'
The dog ate the "flea" -- and 
the
mouse.

arrayBAAD:
declare -a arrayBAAD='([0]="The" [1]="dog" [2]="ate" [3]="the" [4]="\"flea\"" [5]="--" [6]="and" [7]="the" [8]="mouse.")'
The
dog
ate
the
"flea"
--
and
the
mouse.
> 
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.