web-dev-qa-db-fra.com

Comment utiliser des arguments comme $ 1 $ 2 ... dans une boucle for?

J'ai ce script qui a conçu pour télécharger la prononciation des mots que vous lui donnez comme argument:

#!/bin/bash 
m=$#
for ((i=1;i<=m;i++));do

echo $i
#wget https://ssl.gstatic.com/dictionary/static/sounds/de/0/"$i".mp3
done

si je l'exécute par cette commande

./a.sh personality brave selfish

il devrait imprimer sur la sortie standard

personality 
brave 
selfish

mais à la place, il imprime

1
2
3

pourriez-vous m'aider à résoudre ce problème?

p.s: Si j'écris le script sans boucle avec $ 1 par exemple, cela fonctionnera correctement mais je veux télécharger plusieurs fichiers en même temps

16
AmirrezaFiroozi

Dans tout Shell Bourne-like, c'est:

for arg
do printf 'Something with "%s"\n' "$arg"
done

Autrement dit, for fait une boucle sur les paramètres positionnels ($1, $2 ...) par défaut (si vous ne donnez pas de partie in ... ).

Notez que c'est plus portable que:

for arg; do
  printf 'Something with "%s"\n' "$arg"
done

Ce qui n'était pas POSIX avant l'édition 2016 de la norme ni Bourne (bien que fonctionne dans la plupart des autres shells de type Bourne, y compris bash même en mode POSIX)

Ou que:

for arg in "$@"; do
  printf 'Something with "%s"\n' "$arg"
done

Qui est POSIX mais ne fonctionne pas correctement dans le Bourne Shell ou ksh88 lorsque $IFS Ne contient pas le caractère espace, ou avec certaines versions du Bourne Shell quand il n'y a pas d'argument, ou avec certains shells (y compris certains versions de bash) lorsqu'il n'y a pas d'argument et que l'option -u est activée.

Ou que

for arg do
  printf 'Something with "%s"\n' "$arg"
done

qui est POSIX et Bourne mais ne fonctionne pas dans les très vieilles coquilles à base de cendres. Personnellement, j'ignore cela et j'utilise cette syntaxe moi-même car je trouve que c'est la plus lisible et je ne m'attends pas à ce que le code que j'écris finisse par être interprété par un shell aussi arcanique.

Plus d'infos sur:


Maintenant, si vous voulez que $i Passe en boucle sur [1..$#] Et accède aux éléments correspondants, vous pouvez faire:

dans n'importe quel shell POSIX:

i=1
for arg do
  printf '%s\n' "Arg $i: $arg"
  i=$((i + 1))
done

ou:

i=1
while [ "$i" -le "$#" ]; do
  eval "arg=\${$i}"
  printf '%s\n' "Arg $i: $arg"
  i=$((i + 1))
done

Ou avec bash

for ((i = 1; i <= $#; i++ )); do
  printf '%s\n' "Arg $i: ${!i}"
done

${!i} Étant une extension de variable indirecte, qui est développée au contenu du paramètre dont le nom est stocké dans la variable i, similaire au paramètre zsh de P drapeau d'expansion:

for ((i = 1; i <= $#; i++ )); do
  printf '%s\n' "Arg $i: ${(P)i}"
done

Bien que dans zsh, vous pouvez également accéder aux paramètres de position via le tableau $argv (Comme dans csh):

for ((i = 1; i <= $#; i++ )); do
  printf '%s\n' "Arg $i: $argv[i]"
done
37

J'utiliserais shift. Celui-là [ -n "$1" ] signifie que arg-1 n'est pas vide, continuez à boucler.

#! /bin/bash 
while [ -n "$1" ]; do
  echo "$1"
  wget "https://ssl.gstatic.com/dictionary/static/sounds/de/0/$1.mp3"
  shift
done
3
hschou

Manière la plus simple

#!/bin/bash
for i
do
 echo $i
done

et courir

./a.sh personality brave selfish

et voici l'impression sur la stdout

personality
brave
selfish
0
Karthik Marri