Wie verwende ich Argumente wie $1 $2 ... in einer For-Schleife?

Wie verwende ich Argumente wie $1 $2 ... in einer For-Schleife?

Ich habe dieses Skript, das die Aussprache der Wörter herunterlädt, die Sie als Argument eingeben:

#!/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

wenn ich es mit diesem Befehl ausführe

./a.sh personality brave selfish

es sollte auf der Standardausgabe gedruckt werden

personality 
brave 
selfish

aber stattdessen druckt es

1
2
3

würden Sie mir helfen, dieses Problem zu lösen?

ps: Wenn ich das Skript ohne for-Schleife mit $1 schreibe, funktioniert es beispielsweise korrekt, aber ich möchte mehrere Dateien gleichzeitig herunterladen

Antwort1

In jeder Bourne-ähnlichen Shell ist es:

for arg
do printf 'Something with "%s"\n' "$arg"
done

Das heißt, dass standardmäßig foreine Schleife für die Positionsparameter ( $1, ...) ausgeführt wird (wenn Sie keinen Teil angeben).$2in ...

Beachten Sie, dass dies portabler ist als:

for arg; do
  printf 'Something with "%s"\n' "$arg"
done

Was bis zur Ausgabe 2016 des Standards weder POSIX noch Bourne war (funktioniert jedoch in den meisten anderen Bourne-ähnlichen Shells, bashsogar im POSIX-Modus)

Oder als:

for arg in "$@"; do
  printf 'Something with "%s"\n' "$arg"
done

Dies ist POSIX, funktioniert aber in der Bourne-Shell oder in ksh88 nicht richtig, wenn $IFSdas Leerzeichen nicht enthalten ist, oder bei einigen Versionen der Bourne-Shell, wenn kein Argument vorhanden ist, oder bei einigen Shells (einschließlich einiger Versionen von bash), wenn kein Argument vorhanden ist und die -uOption aktiviert ist.

Oder als

for arg do
  printf 'Something with "%s"\n' "$arg"
done

Das ist POSIX und Bourne, funktioniert aber nicht in sehr alten, auf Ash basierenden Shells. Ich persönlich ignoriere das und verwende diese Syntax selbst, da ich sie für die lesbarste halte und nicht erwarte, dass der Code, den ich schreibe, jemals von einer so geheimnisvollen Shell interpretiert wird.

Mehr Infos unter:


$iWenn Sie nun eine Schleife ausführen und auf die entsprechenden Elemente zugreifen möchten [1..$#], haben Sie folgende Möglichkeiten:

in jeder POSIX-Shell:

i=1
for arg do
  printf '%s\n' "Arg $i: $arg"
  i=$((i + 1))
done

oder:

i=1
while [ "$i" -le "$#" ]; do
  eval "arg=\${$i}"
  printf '%s\n' "Arg $i: $arg"
  i=$((i + 1))
done

Oder mitbash

for ((i = 1; i <= $#; i++ )); do
  printf '%s\n' "Arg $i: ${!i}"
done

${!i}Dabei handelt es sich um eine indirekte Variablenerweiterung, d. h., sie wird auf den Inhalt des Parameters erweitert, dessen Name in der iVariablen gespeichert ist, ähnlich dem Parametererweiterungsflag zshvon :P

for ((i = 1; i <= $#; i++ )); do
  printf '%s\n' "Arg $i: ${(P)i}"
done

Obwohl zshSie in auch über das Array auf Positionsparameter zugreifen können $argv(wie in csh):

for ((i = 1; i <= $#; i++ )); do
  printf '%s\n' "Arg $i: $argv[i]"
done

Antwort2

Ich würde verwenden shift. Das [ -n "$1" ]bedeutet, dass die Schleife fortgesetzt wird, solange arg-1 nicht leer ist.

#! /bin/bash 
while [ -n "$1" ]; do
  echo "$1"
  wget "https://ssl.gstatic.com/dictionary/static/sounds/de/0/$1.mp3"
  shift
done

Antwort3

Einfachster Weg

#!/bin/bash
for i
do
 echo $i
done

und Renn

./a.sh personality brave selfish

und hier ist der Ausdruck auf der Standardausgabe

personality
brave
selfish

verwandte Informationen