
Eu tenho este script que foi projetado para baixar a pronúncia das palavras que você fornece 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
se eu executá-lo com este comando
./a.sh personality brave selfish
deve imprimir no stdout
personality
brave
selfish
mas em vez disso ele imprime
1
2
3
você me ajudaria a resolver esse problema?
ps: Se eu escrever o script sem loop for com $1 por exemplo, ele funcionará corretamente, mas quero baixar muitos arquivos ao mesmo tempo
Responder1
Em qualquer shell do tipo Bourne, é:
for arg
do printf 'Something with "%s"\n' "$arg"
done
Ou seja, for
faz um loop nos parâmetros posicionais ( $1
, $2
...) por padrão (se você não der uma in ...
parte).
Observe que isso é mais portátil do que:
for arg; do
printf 'Something with "%s"\n' "$arg"
done
Que não era POSIX até a edição de 2016 do padrão nem Bourne (embora funcione na maioria dos outros shells do tipo Bourne, inclusive bash
no modo POSIX)
Ou então:
for arg in "$@"; do
printf 'Something with "%s"\n' "$arg"
done
Que é POSIX, mas não funciona corretamente no Bourne Shell ou ksh88 quando $IFS
não contém o caractere de espaço, ou com algumas versões do Bourne Shell quando não há argumento, ou com alguns shells (incluindo algumas versões de bash
) quando não há argumento e a -u
opção está habilitada.
Ou então
for arg do
printf 'Something with "%s"\n' "$arg"
done
que é POSIX e Bourne, mas não funciona em shells muito antigos baseados em ash. Eu pessoalmente ignoro isso e uso essa sintaxe, pois acho que é a mais legível e não espero que nenhum código que escrevo acabe sendo interpretado por um shell tão misterioso.
Mais informações em:
- http://www.in-ulm.de/~mascheck/various/bourne_args/
- Qual é o propósito da palavra-chave “do” nos loops for do Bash?
Agora, se quiser $i
fazer um loop [1..$#]
e acessar os elementos correspondentes, você pode fazer:
em qualquer 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 combash
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${!i}"
done
${!i}
sendo uma expansão de variável indireta, que se expande para o conteúdo do parâmetro cujo nome está armazenado na i
variável, semelhante ao sinalizador de expansão de parâmetro zsh
de :P
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${(P)i}"
done
Embora em zsh
, você também pode acessar parâmetros posicionais por meio do $argv
array (como em csh
):
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: $argv[i]"
done
Responder2
Eu usaria shift
. Este [ -n "$1" ]
significa que enquanto arg-1 não estiver vazio, continue em loop.
#! /bin/bash
while [ -n "$1" ]; do
echo "$1"
wget "https://ssl.gstatic.com/dictionary/static/sounds/de/0/$1.mp3"
shift
done
Responder3
Caminho mais fácil
#!/bin/bash
for i
do
echo $i
done
e corra
./a.sh personality brave selfish
e aqui está a impressão no stdout
personality
brave
selfish