Как использовать аргументы типа $1 $2 ... в цикле for?

Как использовать аргументы типа $1 $2 ... в цикле for?

У меня есть этот скрипт, который предназначен для загрузки произношения слов, которые вы указываете в качестве аргумента:

#!/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. Я лично игнорирую это и использую этот синтаксис сам, поскольку считаю его наиболее понятным и не ожидаю, что какой-либо код, который я пишу, когда-либо будет интерпретирован такой загадочной оболочкой.

Более подробная информация на сайте:


Теперь, если вы хотите $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

Связанный контент