
У меня есть этот скрипт, который предназначен для загрузки произношения слов, которые вы указываете в качестве аргумента:
#!/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
если я запущу его этой командой
./a.sh personality brave selfish
он должен вывести на стандартный вывод
personality
brave
selfish
но вместо этого он печатает
1
2
3
Не могли бы вы помочь мне решить эту проблему?
ps: Если я напишу скрипт без цикла for с $1, например, он будет работать правильно, но я хочу загрузить много файлов одновременно
решение1
В любой оболочке типа Bourne это:
for arg
do printf 'Something with "%s"\n' "$arg"
done
То есть, по умолчанию for
выполняется цикл по позиционным параметрам ( $1
, $2
...) (если вы не укажете часть in ...
).
Обратите внимание, что это более переносимо, чем:
for arg; do
printf 'Something with "%s"\n' "$arg"
done
Который не был POSIX до издания стандарта 2016 года, ни Bourne (хотя работает в большинстве других оболочек, подобных Bourne, включая bash
даже режим POSIX)
Или чем:
for arg in "$@"; do
printf 'Something with "%s"\n' "$arg"
done
Который соответствует POSIX, но не работает должным образом в оболочке Bourne или ksh88, когда $IFS
не содержит символ пробела, или с некоторыми версиями оболочки Bourne, когда нет аргумента, или с некоторыми оболочками (включая некоторые версии bash
), когда нет аргумента и -u
опция включена.
Или чем
for arg do
printf 'Something with "%s"\n' "$arg"
done
что соответствует POSIX и Bourne, но не работает в очень старых оболочках на основе ash. Я лично игнорирую это и использую этот синтаксис сам, поскольку считаю его наиболее понятным и не ожидаю, что какой-либо код, который я пишу, когда-либо будет интерпретирован такой загадочной оболочкой.
Более подробная информация на сайте:
- http://www.in-ulm.de/~mascheck/various/bourne_args/
- Каково назначение ключевого слова «do» в циклах Bash?
Теперь, если вы хотите $i
выполнить цикл [1..$#]
и получить доступ к соответствующим элементам, вы можете сделать следующее:
в любой оболочке POSIX:
i=1
for arg do
printf '%s\n' "Arg $i: $arg"
i=$((i + 1))
done
или:
i=1
while [ "$i" -le "$#" ]; do
eval "arg=\${$i}"
printf '%s\n' "Arg $i: $arg"
i=$((i + 1))
done
Или сbash
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${!i}"
done
${!i}
являясь косвенным расширением переменной, то есть расширяясь до содержимого параметра, имя которого хранится в i
переменной, аналогично флагу расширения параметра zsh
:P
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: ${(P)i}"
done
Хотя в zsh
вы также можете получить доступ к позиционным параметрам через $argv
массив (как в csh
):
for ((i = 1; i <= $#; i++ )); do
printf '%s\n' "Arg $i: $argv[i]"
done
решение2
Я бы использовал shift
. Это [ -n "$1" ]
означает, что пока arg-1 непустой, продолжать цикл.
#! /bin/bash
while [ -n "$1" ]; do
echo "$1"
wget "https://ssl.gstatic.com/dictionary/static/sounds/de/0/$1.mp3"
shift
done
решение3
Самый простой способ
#!/bin/bash
for i
do
echo $i
done
и беги
./a.sh personality brave selfish
и вот вывод на stdout
personality
brave
selfish