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.