Übergeben von Arrays als Parameter in Bash

188

Wie kann ich ein Array als Parameter an eine Bash-Funktion übergeben?

Hinweis: Nachdem ich hier auf Stack Overflow keine Antwort gefunden habe, habe ich meine etwas grobe Lösung selbst veröffentlicht. Es kann nur ein Array übergeben werden, und es ist das letzte Element der Parameterliste. Eigentlich übergibt es das Array überhaupt nicht, sondern eine Liste seiner Elemente, die durch call_function () zu einem Array zusammengesetzt werden, aber es hat bei mir funktioniert. Wenn jemand einen besseren Weg kennt, können Sie ihn hier hinzufügen.

DevSolar
quelle
1
Hier haben Sie eine schöne Referenz und jede Menge Beispiele.
Artem Barger
16
Ähm ... Drei Abstimmungen zu einer fünf Jahre alten Frage innerhalb einer Minute?
DevSolar

Antworten:

219

Sie können mehrere Arrays als Argumente übergeben, indem Sie Folgendes verwenden:

takes_ary_as_arg()
{
    declare -a argAry1=("${!1}")
    echo "${argAry1[@]}"

    declare -a argAry2=("${!2}")
    echo "${argAry2[@]}"
}
try_with_local_arys()
{
    # array variables could have local scope
    local descTable=(
        "sli4-iread"
        "sli4-iwrite"
        "sli3-iread"
        "sli3-iwrite"
    )
    local optsTable=(
        "--msix  --iread"
        "--msix  --iwrite"
        "--msi   --iread"
        "--msi   --iwrite"
    )
    takes_ary_as_arg descTable[@] optsTable[@]
}
try_with_local_arys

wird widerhallen:

sli4-iread sli4-iwrite sli3-iread sli3-iwrite  
--msix  --iread --msix  --iwrite --msi   --iread --msi   --iwrite

Bearbeiten / Notizen: (aus Kommentaren unten)

  • descTableund optsTablewerden als Namen übergeben und in der Funktion erweitert. Daher $wird bei der Angabe als Parameter kein Wert benötigt.
  • Beachten Sie, dass dies auch dann funktioniert, wenn descTableetc definiert ist local, da die Einheimischen für die von ihnen aufgerufenen Funktionen sichtbar sind.
  • Das !in ${!1}erweitert die Variable arg 1.
  • declare -a macht das indizierte Array nur explizit, es ist nicht unbedingt notwendig.
Ken Bertelson
quelle
14
Zu beachten ist, dass das Array in der Empfangsfunktion nicht dieselben Indizes hat, wenn das ursprüngliche Array dünn ist.
Bis auf weiteres angehalten.
13
Das ist brillant, aber kann Ken oder jemand ein paar Dinge erklären, die mich verwirren, warum es funktioniert: 1 - Ich hätte gedacht, dass descTable und optsTable $ vorangestellt werden müssten, wenn sie als Funktionsargumente übergeben würden. 2 - Warum ist in der ersten Zeile von "Takes ..." eine explizite Array-Deklaration erforderlich? 3 - Und was macht das! meine im Ausdruck $ {! 1}, und warum ist [@] dort nicht erforderlich oder sogar erlaubt? - Dies funktioniert und all diese Details scheinen aufgrund meiner Tests erforderlich zu sein, aber ich würde gerne verstehen, warum!
Jan Hettich
8
1: descTable und optsTable werden nur als Namen übergeben, daher gibt es kein $, sie sollen nur in der aufgerufenen Funktion 2 erweitert werden: nicht ganz sicher, aber ich denke, es ist nicht wirklich notwendig 3: the! wird verwendet, weil die an die Funktion übergebenen Parameter zweimal erweitert werden müssen: $ 1 wird zu "descTable [@]" erweitert, und das sollte zu "$ {descTable [@]}" erweitert werden. Die $ {! 1} -Syntax macht genau das.
Elmar Zander
8
Ich denke nicht, dass der Teil "deklariere -a" notwendig ist. Das Vorhandensein von Klammern definiert bereits die LHS der Zuweisung als Array.
Erik Aronesty
3
Diese Antwort hat mir gerade geholfen, ein Problem zu lösen. Ich wollte jedoch darauf hinweisen, dass auf meinem Computer (mit Bash 4.3.42) die Anführungszeichen "$ {! 1}" und "$ {! 2}" entfernt werden müssen. Wenn Sie dies nicht tun, wird der Wert des ursprünglichen Arrays als eine Zeichenfolge gelesen und argAry1 [0] bzw. argAry2 [0] zugewiesen, was im Grunde bedeutet, dass die Array-Struktur verloren geht.
Benutzerfreundlich
85

Hinweis: Dies ist die etwas grobe Lösung, die ich selbst veröffentlicht habe, nachdem ich hier auf Stack Overflow keine Antwort gefunden habe. Es kann nur ein Array übergeben werden, und es ist das letzte Element der Parameterliste. Eigentlich übergibt es das Array überhaupt nicht, sondern eine Liste seiner Elemente, die durch call_function () zu einem Array zusammengesetzt werden, aber es hat bei mir funktioniert. Etwas später veröffentlichte Ken seine Lösung, aber ich habe meine hier als "historische" Referenz aufbewahrt.

calling_function()
{
    variable="a"
    array=( "x", "y", "z" )
    called_function "${variable}" "${array[@]}"
}

called_function()
{
    local_variable="${1}"
    shift
    local_array=("${@}")
}

Verbessert von TheBonsai, danke.

DevSolar
quelle
19
Drei Jahre später erhielt diese Antwort - nur aus historischen Gründen aufbewahrt - innerhalb weniger Tage zwei Abstimmungen. Wie bei SO leider üblich, ohne Angabe, warum die Leute dies für gerechtfertigt halten. Beachten Sie, dass diese Antwort älter ist als alle anderen und dass ich Kens Antwort als die beste Lösung akzeptiert habe. Ich bin mir vollkommen bewusst, dass es bei weitem nicht perfekt ist, aber für vier Monate war es das beste, das es auf SO gibt. Warum es zwei Jahre nach dem zweiten Platz nach Kens perfekter Lösung herabgestuft werden sollte, ist mir ein Rätsel .
DevSolar
@geirha: Ich würde Sie bitten zu überprüfen, wer die Frage gestellt hat, wer diese Antwort gepostet hat und wer wahrscheinlich die Antwort akzeptiert hat, die Sie "schlecht" nennen. ;-) Vielleicht möchten Sie auch den Hinweis in der Frage überprüfen , der darauf hinweist, warum diese Lösung der von Ken unterlegen ist.
DevSolar
2
Ich weiß, dass Sie die Frage gestellt haben, diese Antwort geschrieben haben und die schlechte Antwort akzeptiert haben. Deshalb habe ich es so formuliert. Der Grund, warum die akzeptierte Antwort schlecht ist, ist, dass versucht wird, ein Array als Referenz zu übergeben, was Sie wirklich vermeiden sollten. Darüber hinaus werden im Beispiel mehrere Argumente zu einer einzigen Zeichenfolge zusammengefasst. Wenn Sie Arrays wirklich als Referenz übergeben müssen, ist bash zunächst die falsche Sprache. Selbst mit den neuen nameref-Variablen von bash 4.3 können Sie Namenskollisionen (Zirkelverweis) nicht sicher vermeiden.
Geirha
4
Nun, Sie können mehrere Arrays übergeben, wenn Sie die Anzahl der Elemente jedes Arrays angeben. called_function "${#array[@]}" "${array[@]}" "${#array2[@]}" "${array2[@]}"etc ... immer noch mit einigen offensichtlichen Einschränkungen, aber wirklich besser, um das Problem auf eine Weise zu lösen, die die Sprache unterstützt, als zu versuchen, die Sprache so zu biegen, wie Sie es in anderen Sprachen gewohnt sind.
Geirha
1
@geirha: Nun, ich denke, wir müssen zustimmen, dass wir nicht zustimmen, und Sie müssen mich als Richter bestimmen lassen, welche Antwort meine Frage am besten beantwortet. Persönlich ziehe ich es sowieso vor, Arrays als Referenz zu übergeben (unabhängig von der Sprache, um das Kopieren der Daten zu speichern);
Dies gilt
38

Kommentar zur Ken Bertelson-Lösung und Beantwortung von Jan Hettich:

Wie es funktioniert

Die takes_ary_as_arg descTable[@] optsTable[@]Line-In- try_with_local_arys()Funktion sendet:

  1. Dies ist tatsächlich schafft eine Kopie des descTableund optsTableArrays , die auf die zugegriffen werden kann takes_ary_as_argFunktion.
  2. takes_ary_as_arg()Funktion empfängt descTable[@]und optsTable[@]als Zeichenfolgen, das heißt $1 == descTable[@]und $2 == optsTable[@].
  3. Zu Beginn der takes_ary_as_arg()Funktion wird die ${!parameter}Syntax verwendet, die als indirekte Referenz oder manchmal als doppelte Referenz bezeichnet wird. Dies bedeutet, dass anstelle des $1Werts von 'der Wert des erweiterten Werts von$1 beispielsweise verwendet wird:

    baba=booba
    variable=baba
    echo ${variable} # baba
    echo ${!variable} # booba

    ebenfalls für $2.

  4. Wenn Sie dies argAry1=("${!1}")einfügen, wird es argAry1als Array (die folgenden Klammern =) mit dem erweiterten erstellt descTable[@], genau wie wenn Sie argAry1=("${descTable[@]}")direkt dort schreiben . das declaregibt es nicht.

NB: Es ist erwähnenswert, dass die Array-Initialisierung mit diesem Klammerformular das neue Array gemäß dem IFSoder internen Feldtrennzeichen initialisiert, das standardmäßig Registerkarte , Zeilenumbruch und Leerzeichen ist . in diesem Fall wird, da es die [@]Notation verwendet, jedes Element für sich gesehen, als ob es zitiert worden wäre (im Gegensatz zu [*]).

Meine Reservierung damit

Der BASHlokale Variablenbereich ist die aktuelle Funktion und jede von ihr aufgerufene untergeordnete Funktion. Dies bedeutet, dass die takes_ary_as_arg()Funktion diese descTable[@]und optsTable[@]Arrays "sieht" und somit funktioniert (siehe obige Erklärung).

Schauen Sie sich in diesem Fall diese Variablen direkt an. Es ist wie dort zu schreiben:

argAry1=("${descTable[@]}")

Siehe obige Erklärung, in der nur descTable[@]die Werte des Arrays entsprechend dem aktuellen Wert kopiert werden IFS.

Zusammenfassend

Dies ist im Wesentlichen nichts Wertvolles - wie üblich.

Ich möchte auch den obigen Kommentar von Dennis Williamson hervorheben: Spärliche Arrays (Arrays ohne alle definierten Schlüssel - mit "Löchern" darin) funktionieren nicht wie erwartet - wir würden die Schlüssel verlieren und das Array "verdichten".

Davon abgesehen sehe ich den Wert für die Verallgemeinerung, Funktionen können also die Arrays (oder Kopien) erhalten, ohne die Namen zu kennen:

  • für ~ "Kopien": Diese Technik ist gut genug, muss nur beachten, dass die Indizes (Schlüssel) weg sind.
  • für echte Kopien: Wir können eine Auswertung für die Schlüssel verwenden, zum Beispiel:

    eval local keys=(\${!$1})

und dann eine Schleife, mit der eine Kopie erstellt wird. Hinweis: Hier !wird nicht die vorherige indirekte / doppelte Auswertung verwendet, sondern im Array-Kontext werden die Array-Indizes (Schlüssel) zurückgegeben.

  • und wenn wir natürlich übergeben descTableund optsTableZeichenfolgen (ohne [@]) übergeben würden, könnten wir das Array selbst (wie in der Referenz) mit verwenden eval. für eine generische Funktion, die Arrays akzeptiert.
Der Zauberer
quelle
2
Gute Erklärungen des Mechanismus hinter der Erklärung von Ken Bertelson. Auf die Frage "In diesem Fall, warum nicht direkt auf diese Variablen selbst schauen?" Werde ich antworten: einfach zur Wiederverwendung der Funktion. Nehmen wir an, ich muss eine Funktion aufrufen Array1, dann Array2wird es praktisch, die Array-Namen zu übergeben.
Gfrigon
Tolle Antwort, wir brauchen mehr Erklärungen wie diese!
Édouard Lopez
21

Das Grundproblem hierbei ist, dass die Bash-Entwickler, die Arrays entworfen / implementiert haben, das Hündchen wirklich durcheinander gebracht haben. Sie entschieden, dass dies ${array}nur eine kurze Hand war ${array[0]}, was ein schlimmer Fehler war. Besonders wenn Sie bedenken, dass dies ${array[0]}keine Bedeutung hat und als leere Zeichenfolge ausgewertet wird, wenn der Array-Typ assoziativ ist.

Das Zuweisen eines Arrays erfolgt in der Form, array=(value1 ... valueN)in der value die Syntax hat [subscript]=string, wodurch ein Wert direkt einem bestimmten Index im Array zugewiesen wird. Dies macht es so, dass es zwei Arten von Arrays geben kann, numerisch indiziert und Hash-indiziert (im Bash-Sprachgebrauch assoziative Arrays genannt). Es macht es auch so, dass Sie spärliche numerisch indizierte Arrays erstellen können. Das Weglassen des [subscript]=Teils ist eine kurze Hand für ein numerisch indiziertes Array, beginnend mit dem Ordnungsindex 0 und inkrementierend mit jedem neuen Wert in der Zuweisungsanweisung.

Daher ${array}sollte auf das gesamte Array, Indizes und alle ausgewertet werden . Es sollte umgekehrt zur Zuweisungsanweisung ausgewertet werden. Jeder CS-Major im dritten Jahr sollte das wissen. In diesem Fall würde dieser Code genau so funktionieren, wie Sie es erwarten würden:

declare -A foo bar
foo=${bar}

Dann würde das Übergeben von Arrays nach Wert an Funktionen und das Zuweisen eines Arrays zu einem anderen funktionieren, wie es der Rest der Shell-Syntax vorschreibt. Da sie dies jedoch nicht richtig gemacht haben, =funktioniert der Zuweisungsoperator nicht für Arrays, und Arrays können nicht als Wert an Funktionen oder Subshells übergeben oder allgemein ausgegeben werden ( echo ${array}), ohne dass Code zum Durchkauen verwendet wird .

Wenn es also richtig gemacht worden wäre, würde das folgende Beispiel zeigen, wie die Nützlichkeit von Arrays in Bash wesentlich besser sein könnte:

simple=(first=one second=2 third=3)
echo ${simple}

Die resultierende Ausgabe sollte sein:

(first=one second=2 third=3)

Dann könnten Arrays den Zuweisungsoperator verwenden und als Wert an Funktionen und sogar andere Shell-Skripte übergeben werden. Einfach durch Ausgabe in eine Datei zu speichern und einfach aus einer Datei in ein Skript zu laden.

declare -A foo
read foo <file

Leider wurden wir von einem Bash-Entwicklungsteam der Superlative enttäuscht.

Um ein Array an eine Funktion zu übergeben, gibt es wirklich nur eine Option, nämlich die Verwendung der Funktion nameref:

function funky() {
    local -n ARR

    ARR=$1
    echo "indexes: ${!ARR[@]}"
    echo "values: ${ARR[@]}"
}

declare -A HASH

HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function

führt zu folgender Ausgabe:

indexes: foo zoom
values: bar fast

Da dies als Referenz übergeben wird, können Sie dem Array in der Funktion auch zuweisen. Ja, das Array, auf das verwiesen wird, muss einen globalen Bereich haben, aber das sollte keine allzu große Sache sein, wenn man bedenkt, dass es sich um Shell-Scripting handelt. Um ein assoziatives oder dünn indiziertes Array nach Wert an eine Funktion zu übergeben, müssen alle Indizes und Werte als einzelne Zeichenfolgen wie folgt in die Argumentliste geworfen werden (nicht allzu nützlich, wenn es sich um ein großes Array handelt):

funky "${!array[*]}" "${array[*]}"

und dann eine Reihe von Code in die Funktion schreiben, um das Array wieder zusammenzusetzen.

Tigerand
quelle
1
Die Lösung der Verwendung local -nist besser und aktueller als die akzeptierte Antwort. Diese Lösung funktioniert auch für eine Variable eines beliebigen Typs. Das in dieser Antwort aufgeführte Beispiel kann auf verkürzt werden local -n ARR=${1}. Die -nOption für local/ declareist jedoch nur in Bash Version 4.3 und höher verfügbar.
richardjsimkins
Das ist nett! Kleines Problem: Wenn Sie eine Variable mit demselben Namen wie das lokale Argument Ihrer Funktion übergeben (z. B. funky ARR), gibt die Shell eine Warnung aus circular name reference, da die Funktion im Grunde versucht, dies zu tun local -n ARR=ARR. Gute Diskussion zu diesem Thema.
Gene Pavlovsky
5

Die Antwort von DevSolar hat einen Punkt, den ich nicht verstehe (vielleicht hat er einen bestimmten Grund dafür, aber mir fällt keiner ein): Er setzt das Array aus den Positionsparametern Element für Element iterativ.

Ein einfacher Ansatz wäre

called_function()
{
  ...
  # do everything like shown by DevSolar
  ...

  # now get a copy of the positional parameters
  local_array=("$@")
  ...
}
TheBonsai
quelle
1
Mein Grund dafür ist, dass ich bis vor ein paar Tagen überhaupt nicht mit Bash-Arrays gespielt habe. Zuvor wäre ich zu Perl gewechselt, wenn es komplex geworden wäre, eine Option, die ich bei meinem aktuellen Job nicht habe. Danke für den Tipp!
DevSolar
3
function aecho {
  set "$1[$2]"
  echo "${!1}"
}

Beispiel

$ foo=(dog cat bird)

$ aecho foo 1
cat
Steven Penny
quelle
3

Eine einfache Möglichkeit, mehrere Arrays als Parameter zu übergeben, besteht darin, eine durch Zeichen getrennte Zeichenfolge zu verwenden. Sie können Ihr Skript folgendermaßen aufrufen:

./myScript.sh "value1;value2;value3" "somethingElse" "value4;value5" "anotherOne"

Dann können Sie es wie folgt in Ihren Code extrahieren:

myArray=$1
IFS=';' read -a myArray <<< "$myArray"

myOtherArray=$3
IFS=';' read -a myOtherArray <<< "$myOtherArray"

Auf diese Weise können Sie tatsächlich mehrere Arrays als Parameter übergeben, und es müssen nicht die letzten Parameter sein.

Remy Cilia
quelle
1

Dieser funktioniert auch mit Leerzeichen:

format="\t%2s - %s\n"

function doAction
{
  local_array=("$@")
  for (( i = 0 ; i < ${#local_array[@]} ; i++ ))
    do
      printf "${format}" $i "${local_array[$i]}"
  done
  echo -n "Choose: "
  option=""
  read -n1 option
  echo ${local_array[option]}
  return
}

#the call:
doAction "${tools[@]}"
bescheidene Sapiens
quelle
2
Ich frage mich, worum es hier geht. Dies ist nur eine normale Argumentation. Die "$ @" -Syntax funktioniert für Leerzeichen: "$ @" entspricht "$ 1" "$ 2" ...
Andreas Spindler
Kann ich 2 Arrays an eine Funktion übergeben?
pihentagy
1

Mit ein paar Tricks können Sie benannte Parameter zusammen mit Arrays an Funktionen übergeben.

Mit der von mir entwickelten Methode können Sie auf Parameter zugreifen, die an eine Funktion wie die folgende übergeben wurden:

testPassingParams() {

    @var hello
    l=4 @array anArrayWithFourElements
    l=2 @array anotherArrayWithTwo
    @var anotherSingle
    @reference table   # references only work in bash >=4.3
    @params anArrayOfVariedSize

    test "$hello" = "$1" && echo correct
    #
    test "${anArrayWithFourElements[0]}" = "$2" && echo correct
    test "${anArrayWithFourElements[1]}" = "$3" && echo correct
    test "${anArrayWithFourElements[2]}" = "$4" && echo correct
    # etc...
    #
    test "${anotherArrayWithTwo[0]}" = "$6" && echo correct
    test "${anotherArrayWithTwo[1]}" = "$7" && echo correct
    #
    test "$anotherSingle" = "$8" && echo correct
    #
    test "${table[test]}" = "works"
    table[inside]="adding a new value"
    #
    # I'm using * just in this example:
    test "${anArrayOfVariedSize[*]}" = "${*:10}" && echo correct
}

fourElements=( a1 a2 "a3 with spaces" a4 )
twoElements=( b1 b2 )
declare -A assocArray
assocArray[test]="works"

testPassingParams "first" "${fourElements[@]}" "${twoElements[@]}" "single with spaces" assocArray "and more... " "even more..."

test "${assocArray[inside]}" = "adding a new value"

Mit anderen Worten, Sie können Ihre Parameter nicht nur bei ihren Namen aufrufen (was einen besser lesbaren Kern ausmacht), sondern auch Arrays übergeben (und Verweise auf Variablen - diese Funktion funktioniert jedoch nur in Bash 4.3)! Außerdem befinden sich die zugeordneten Variablen alle im lokalen Bereich, genau wie $ 1 (und andere).

Der Code, mit dem dies funktioniert, ist ziemlich leicht und funktioniert sowohl in Bash 3 als auch in Bash 4 (dies sind die einzigen Versionen, mit denen ich es getestet habe). Wenn Sie an weiteren Tricks wie diesen interessiert sind, die das Entwickeln mit Bash viel schöner und einfacher machen, können Sie sich mein Bash Infinity Framework ansehen. Der folgende Code wurde für diesen Zweck entwickelt.

Function.AssignParamLocally() {
    local commandWithArgs=( $1 )
    local command="${commandWithArgs[0]}"

    shift

    if [[ "$command" == "trap" || "$command" == "l="* || "$command" == "_type="* ]]
    then
        paramNo+=-1
        return 0
    fi

    if [[ "$command" != "local" ]]
    then
        assignNormalCodeStarted=true
    fi

    local varDeclaration="${commandWithArgs[1]}"
    if [[ $varDeclaration == '-n' ]]
    then
        varDeclaration="${commandWithArgs[2]}"
    fi
    local varName="${varDeclaration%%=*}"

    # var value is only important if making an object later on from it
    local varValue="${varDeclaration#*=}"

    if [[ ! -z $assignVarType ]]
    then
        local previousParamNo=$(expr $paramNo - 1)

        if [[ "$assignVarType" == "array" ]]
        then
            # passing array:
            execute="$assignVarName=( \"\${@:$previousParamNo:$assignArrLength}\" )"
            eval "$execute"
            paramNo+=$(expr $assignArrLength - 1)

            unset assignArrLength
        elif [[ "$assignVarType" == "params" ]]
        then
            execute="$assignVarName=( \"\${@:$previousParamNo}\" )"
            eval "$execute"
        elif [[ "$assignVarType" == "reference" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        elif [[ ! -z "${!previousParamNo}" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        fi
    fi

    assignVarType="$__capture_type"
    assignVarName="$varName"
    assignArrLength="$__capture_arrLength"
}

Function.CaptureParams() {
    __capture_type="$_type"
    __capture_arrLength="$l"
}

alias @trapAssign='Function.CaptureParams; trap "declare -i \"paramNo+=1\"; Function.AssignParamLocally \"\$BASH_COMMAND\" \"\$@\"; [[ \$assignNormalCodeStarted = true ]] && trap - DEBUG && unset assignVarType && unset assignVarName && unset assignNormalCodeStarted && unset paramNo" DEBUG; '
alias @param='@trapAssign local'
alias @reference='_type=reference @trapAssign local -n'
alias @var='_type=var @param'
alias @params='_type=params @param'
alias @array='_type=array @param'
niieani
quelle
1

Nur um die akzeptierte Antwort zu ergänzen, da ich festgestellt habe, dass es nicht gut funktioniert, wenn der Array-Inhalt wie folgt aussieht:

RUN_COMMANDS=(
  "command1 param1... paramN"
  "command2 param1... paramN"
)

In diesem Fall wird jedes Mitglied des Arrays aufgeteilt, sodass das Array, das die Funktion sieht, entspricht:

RUN_COMMANDS=(
    "command1"
    "param1"
     ...
    "command2"
    ...
)

Um diesen Fall zum Laufen zu bringen, habe ich den Variablennamen an die Funktion übergeben und dann eval verwendet:

function () {
    eval 'COMMANDS=( "${'"$1"'[@]}" )'
    for COMMAND in "${COMMANDS[@]}"; do
        echo $COMMAND
    done
}

function RUN_COMMANDS

Nur meine 2 ©

AlvaroGMJ
quelle
1

So hässlich es auch ist, hier ist eine Problemumgehung, die funktioniert, solange Sie kein Array explizit übergeben, sondern eine Variable, die einem Array entspricht:

function passarray()
{
    eval array_internally=("$(echo '${'$1'[@]}')")
    # access array now via array_internally
    echo "${array_internally[@]}"
    #...
}

array=(0 1 2 3 4 5)
passarray array # echo's (0 1 2 3 4 5) as expected

Ich bin sicher, dass jemand eine klarere Implementierung der Idee finden kann, aber ich habe festgestellt, dass dies eine bessere Lösung ist, als ein Array als zu übergeben "{array[@]"}und dann intern mit darauf zuzugreifen array_inside=("$@"). Dies wird kompliziert, wenn andere Positions- / getoptsParameter vorhanden sind. In diesen Fällen musste ich zuerst die Parameter bestimmen und dann entfernen, die nicht mit dem Array verknüpft sind, indem ich eine Kombination aus shiftund Entfernen von Array-Elementen verwendete.

Eine puristische Perspektive betrachtet diesen Ansatz wahrscheinlich als eine Verletzung der Sprache, aber pragmatisch gesehen hat mir dieser Ansatz viel Kummer erspart. Zu einem verwandten Thema verwende ich auch eval, um einer Variablen, die nach einem Parameter benannt ist, den target_varnameich an die Funktion übergebe , ein intern erstelltes Array zuzuweisen :

eval $target_varname=$"(${array_inside[@]})"

Hoffe das hilft jemandem.

Blake Schultze
quelle
0

Voraussetzung : Funktion zum Suchen einer Zeichenfolge in einem Array.
Dies ist eine leichte Vereinfachung der DevSolar-Lösung, da die übergebenen Argumente verwendet werden, anstatt sie zu kopieren.

myarray=('foobar' 'foxbat')

function isInArray() {
  local item=$1
  shift
  for one in $@; do
    if [ $one = $item ]; then
      return 0   # found
    fi
  done
  return 1       # not found
}

var='foobar'
if isInArray $var ${myarray[@]}; then
  echo "$var found in array"
else
  echo "$var not found in array"
fi 
Andre
quelle
0

Meine kurze Antwort lautet:

function display_two_array {
    local arr1=$1
    local arr2=$2
    for i in $arr1
    do
       "arrary1: $i"
    done
    
    for i in $arr2
    do
       "arrary2: $i"
    done
}

test_array=(1 2 3 4 5)
test_array2=(7 8 9 10 11)

display_two_array "${test_array[*]}" "${test_array2[*]}"
Es sollte beachtet werden, dass das ${test_array[*]}und ${test_array2[*]}von "" umgeben sein sollte, sonst scheitern Sie.

tOmMy
quelle
Ihr Beispiel ist falsch, weil es unvollständig ist. Bitte geben Sie den vollständigen Code des Skripts an.
Dennis VR