
引数として指定した単語の発音をダウンロードするように設計されたこのスクリプトがあります:
#!/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: たとえば$1でforループなしでスクリプトを書くと、正しく動作しますが、同時に多くのファイルをダウンロードしたいのです
答え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
これは、2016 年版の標準まで POSIX ではなく、Bourne でもありません (ただし、bash
POSIX モードを含む他のほとんどの Bourne 系シェルでは動作します)。
または:
for arg in "$@"; do
printf 'Something with "%s"\n' "$arg"
done
これは POSIX ですが、 に$IFS
スペース文字が含まれていない場合、または引数がない場合の一部の Bourne シェルのバージョン、または引数がなくオプションが有効になっている一部のシェル ( の一部のバージョンを含むbash
) では、 Bourne シェルまたは ksh88 では-u
正しく動作しません。
あるいは
for arg do
printf 'Something with "%s"\n' "$arg"
done
これは POSIX と Bourne ですが、非常に古い ash ベースのシェルでは動作しません。私は個人的にはこれを無視して、この構文を使用しています。これが最も読みやすいと思うからです。また、私が書いたコードがこのような難解なシェルで解釈されることは期待していません。
詳細情報:
$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
そしてこれが標準出力に出力されるものです
personality
brave
selfish