¿Cómo utilizar argumentos como $1 $2... en un bucle for?

¿Cómo utilizar argumentos como $1 $2... en un bucle for?

Tengo este script diseñado para descargar la pronunciación de las palabras que le das como argumento:

#!/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 lo ejecuto con este comando

./a.sh personality brave selfish

debería imprimirse en la salida estándar

personality 
brave 
selfish

pero en lugar de eso imprime

1
2
3

¿me ayudarías a resolver este problema?

ps: si escribo el script sin bucle for con $1, por ejemplo, funcionará correctamente pero quiero descargar muchos archivos al mismo tiempo

Respuesta1

En cualquier caparazón tipo Bourne, es:

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

Es decir, forrealiza un bucle en los parámetros posicionales ( $1, $2...) de forma predeterminada (si no proporciona una in ...parte).

Tenga en cuenta que eso es más portátil que:

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

Que no era POSIX hasta la edición 2016 del estándar ni Bourne (aunque funciona en la mayoría de los demás shells tipo Bourne, incluso bashen modo POSIX)

O que:

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

Que es POSIX pero no funciona correctamente en el shell Bourne o ksh88 cuando $IFSno contiene el carácter de espacio, o con algunas versiones del shell Bourne cuando no hay argumentos, o con algunos shells (incluidas algunas versiones de bash) cuando no hay argumento y la -uopción está habilitada.

o que

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

que es POSIX y Bourne pero no funciona en shells muy antiguos basados ​​en cenizas. Personalmente, lo ignoro y uso esa sintaxis porque encuentro que es la más legible y no espero que el código que escribo termine interpretado por un shell tan arcano.

Más información en:


Ahora, si desea $irecorrer [1..$#]y acceder a los elementos correspondientes, puede hacer:

en cualquier shell POSIX:

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

o:

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

O conbash

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

${!i}siendo una expansión de variable indirecta, es decir, se expande al contenido del parámetro cuyo nombre está almacenado en la ivariable, similar al indicador de expansión de parámetro zshde 's :P

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

Aunque en zsh, también puedes acceder a los parámetros posicionales a través de la $argvmatriz (como en csh):

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

Respuesta2

Yo usaría shift. Esto [ -n "$1" ]significa que mientras arg-1 no esté vacío, siga repitiendo.

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

Respuesta3

La manera más fácil

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

y correr

./a.sh personality brave selfish

y aquí está la impresión en la salida estándar

personality
brave
selfish

información relacionada