
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, for
realiza 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 bash
en 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 $IFS
no 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 -u
opció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:
- http://www.in-ulm.de/~mascheck/various/bourne_args/
- ¿Cuál es el propósito de la palabra clave "do" en Bash para bucles?
Ahora, si desea $i
recorrer [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 i
variable, similar al indicador de expansión de parámetro zsh
de '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 $argv
matriz (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