Konvertieren Sie Befehlszeilenargumente in ein Array in Bash


160

Wie konvertiere ich Befehlszeilenargumente in ein Bash-Skript-Array?

Ich möchte das nehmen:

./something.sh arg1 arg2 arg3

und konvertieren Sie es in

myArray=( arg1 arg2 arg3 )

damit ich myArray zur weiteren Verwendung im Skript verwenden kann.

Dieser vorherige SO-Beitrag kommt dem nahe, befasst sich jedoch nicht mit dem Erstellen eines Arrays: Wie analysiere ich Befehlszeilenargumente in Bash?

Ich muss die Argumente in ein reguläres Bash-Skript-Array konvertieren. Mir ist klar, dass ich andere Sprachen verwenden könnte (z. B. Python), dies aber in Bash tun muss. Ich schätze, ich suche eine "Anhängen" -Funktion oder ähnliches?

UPDATE: Ich wollte auch fragen, wie man nach Null-Argumenten sucht und einen Standard-Array-Wert zuweist, und dank der folgenden Antwort konnte dies funktionieren:

if [ "$#" -eq 0 ]; then
  myArray=( defaultarg1 defaultarg2 )
else
  myArray=( "$@" )
fi

Antworten:


206

Tatsächlich sind Ihre Befehlszeilenargumente praktisch bereits wie ein Array. Zumindest können Sie die $@Variable wie ein Array behandeln. Das heißt, Sie können es in ein tatsächliches Array wie folgt konvertieren:

myArray=( "$@" )

Wenn Sie nur einige Argumente eingeben und in den $@Wert eingeben möchten , verwenden Sie set:

$ set -- apple banana "kiwi fruit"
$ echo "$#"
3
$ echo "$@"
apple banana kiwi fruit

Das Verständnis der Verwendung der Argumentstruktur ist besonders in POSIX sh hilfreich, das nichts anderes als ein Array enthält.


2
Vielen Dank! Funktioniert super! Ich wollte gerade fragen, wie man nach Null-Argumenten sucht und einen Standard-Array-Wert zuweist, und das $ # funktioniert perfekt dafür!
Suman

1
setMit dieser Option können Sie Positionsparameter für den Bereich festlegen. Außerdem können Sie Shell-Optionen festlegen. Sie können dies tun set foo, was bedeutet, dass die $1Erweiterung auf "foo" erfolgt. Wenn Ihre Parameter jedoch mit einem Bindestrich beginnen, setwird davon ausgegangen, dass Sie eine Shell-Option festlegen möchten. Der Doppelstrich stellt sicher, dass alle folgenden Parameter als einzustellende Positionsparameter interpretiert werden.
Kojiro

11
One gotcha: echo $@druckt alle Argumente, aber echo $myArraynur das erste Element. Verwenden Sie, um sie alle zu sehen echo ${myArray[@]}.
z0r

4
@ z0r Wenn Sie diese Erweiterungen nicht in doppelte Anführungszeichen setzen, werden sie durch bash erneut in Wörter aufgeteilt und verlieren möglicherweise an Bedeutung.
Kojiro

Richtig, die allgemeine Möglichkeit, ein Array zu "splat" und jedes Element zu verwenden, ist "${myArray[@]}". Wenn Sie das Array durchlaufen möchten, benötigen Sie die Anführungszeichen, um zu vermeiden, dass die einzelnen Elemente auf IFS
BallpointBen

66

Vielleicht kann das helfen:

myArray=("$@") 

Sie können auch über Argumente iterieren, indem Sie 'in' weglassen:

for arg; do
   echo "$arg"
done

wird gleichwertig sein

for arg in "${myArray[@]}"; do
   echo "$arg"
done

3
Fragen von Neulingen: Woher weiß Bash, was in das argFeld zu setzen ist - ist es eine vordefinierte Variable? ${var}wird auf den Inhalt von erweitert var. ${var[n]}wird auf den Inhalt des Elements ndes Arrays erweitert var. Wird ${var[@]}erweitert dann das gesamte Array, dh ${var[0]} ${var[1]} ... ${var[n]}(mit ndem letzten Element des Index ist)?
Christian

4
[for] without [in] durchläuft das Argumentarray $ @ ($ 1, $ 2 usw.). Was auch mit dem Befehl [set] eingestellt werden kann, zum Beispiel set - arg1 arg2
Nahuel Fouilleul

17

Tatsächlich kann auf die Liste der Parameter mit $1 $2 ...usw. zugegriffen werden .
Dies entspricht genau:

${!i}

Die Liste der Parameter kann also mit set geändert werden
und ${!i}ist der richtige Weg, um darauf zuzugreifen:

$ set -- aa bb cc dd 55 ff gg hh ii jjj kkk lll
$ for ((i=0;i<=$#;i++)); do echo "$#" "$i" "${!i}"; done
12 1 aa
12 2 bb
12 3 cc
12 4 dd
12 5 55
12 6 ff
12 7 gg
12 8 hh
12 9 ii
12 10 jjj
12 11 kkk
12 12 lll

Für Ihren speziellen Fall kann dies verwendet werden (ohne dass Arrays erforderlich sind), um die Liste der Argumente festzulegen, wenn keine angegeben wurden:

if [ "$#" -eq 0 ]; then
    set -- defaultarg1 defaultarg2
fi

was zu diesem noch einfacheren Ausdruck führt:

[ "$#" == "0" ] && set -- defaultarg1 defaultarg2

Sollte das Echo-Beispiel nicht lauten: echo "$#" "$i+1" "${!i}";um die Ausgabe genau wie gezeigt zu erhalten?
Zael

6

Hier ist eine andere Verwendung:

#!/bin/bash
array=( "$@" )
arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   echo "${array[$i]}"
done

4

Einfacher Sie können jedoch direkt arbeiten $@;)

So übergeben Sie eine Liste von Argumenten direkt an der Eingabeaufforderung:

function echoarg { for stuff in "$@" ; do echo $stuff ; done ; } 
    echoarg Hey Ho Lets Go
    Hey
    Ho
    Lets
    Go

1
Noch einfacher, for stuff in "$@" ; do ...ist dasselbe wie for stuff ; do ...:)
km km

1

Nebeneinander Ansicht, wie das Array und $ @ praktisch gleich sind.

Code:

#!/bin/bash

echo "Dollar-1 : $1"
echo "Dollar-2 : $2"
echo "Dollar-3 : $3"
echo "Dollar-AT: $@"
echo ""

myArray=( "$@" )

echo "A Val 0: ${myArray[0]}"
echo "A Val 1: ${myArray[1]}"
echo "A Val 2: ${myArray[2]}"
echo "A All Values: ${myArray[@]}"

Eingang:

./bash-array-practice.sh 1 2 3 4

Ausgabe:

Dollar-1 : 1
Dollar-2 : 2
Dollar-3 : 3
Dollar-AT: 1 2 3 4

A Val 0: 1
A Val 1: 2
A Val 2: 3
A All Values: 1 2 3 4

1

Hervorzuheben ist die Bedeutung der doppelten Anführungszeichen. Angenommen, ein Argument enthält Leerzeichen.

Code:

#!/bin/bash
printf 'arguments:%s\n' "$@"
declare -a arrayGOOD=( "$@" )
declare -a arrayBAAD=(  $@  )

printf '\n%s:\n' arrayGOOD
declare -p arrayGOOD
arrayGOODlength=${#arrayGOOD[@]}
for (( i=1; i<${arrayGOODlength}+1; i++ ));
do
   echo "${arrayGOOD[$i-1]}"
done

printf '\n%s:\n' arrayBAAD
declare -p arrayBAAD
arrayBAADlength=${#arrayBAAD[@]}
for (( i=1; i<${arrayBAADlength}+1; i++ ));
do
   echo "${arrayBAAD[$i-1]}"
done

Ausgabe:

> ./bash-array-practice.sh 'The dog ate the "flea" -- and ' the mouse.
arguments:The dog ate the "flea" -- and 
arguments:the
arguments:mouse.

arrayGOOD:
declare -a arrayGOOD='([0]="The dog ate the \"flea\" -- and " [1]="the" [2]="mouse.")'
The dog ate the "flea" -- and 
the
mouse.

arrayBAAD:
declare -a arrayBAAD='([0]="The" [1]="dog" [2]="ate" [3]="the" [4]="\"flea\"" [5]="--" [6]="and" [7]="the" [8]="mouse.")'
The
dog
ate
the
"flea"
--
and
the
mouse.
> 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.