Przekazywanie tablic jako parametrów w bash

188

Jak mogę przekazać tablicę jako parametr do funkcji bash?

Uwaga: po tym, jak nie znalazłem tutaj odpowiedzi na temat Przepełnienia stosu, sam opublikowałem swoje nieco prymitywne rozwiązanie. Pozwala to na przekazanie tylko jednej tablicy i jest to ostatni element listy parametrów. Właściwie to wcale nie przekazuje tablicy, ale listę jej elementów, które są ponownie składane w tablicę przez wywołanie funkcji_funkcji (), ale działało to dla mnie. Jeśli ktoś zna lepszy sposób, dodaj go tutaj.

DevSolar
źródło
1
Tutaj masz niezłe referencje i mnóstwo przykładów.
Artem Barger
16
Errr ... Trzy głosy negatywne na pięcioletnie pytanie w tej samej minucie?
DevSolar

Odpowiedzi:

220

Jako argumenty możesz przekazać wiele tablic, używając czegoś takiego:

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

wyemituje echo:

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

Edytuj / notatki: (z komentarzy poniżej)

  • descTablei optsTablesą przekazywane jako nazwy i są rozwijane w funkcji. Dlatego nie $jest potrzebny, gdy podano go jako parametry.
  • Zauważ, że nadal działa to nawet przy descTablezdefiniowaniu etc local, ponieważ locals są widoczne dla wywoływanych funkcji.
  • !W ${!1}rozszerza zmiennej arg 1.
  • declare -a sprawia, że ​​indeksowana tablica jest jawna, nie jest to absolutnie konieczne.
Ken Bertelson
źródło
14
Należy zauważyć, że jeśli oryginalna tablica jest rzadka, tablica w funkcji odbierającej nie będzie miała tych samych wskaźników.
Wstrzymano do odwołania.
13
Jest to genialne, ale czy Ken lub ktoś może wyjaśnić kilka zagadek, które mnie zastanawiają, dlaczego to działa: 1 - Myślałem, że descTable i optsTable musiałyby być poprzedzone znakiem $, gdy były przekazywane jako argumenty funkcji. 2 - Dlaczego w pierwszym wierszu „trwa ...” potrzebna jest wyraźna deklaracja tablicowa? 3 - A co robi! oznacza w wyrażeniu $ {! 1} i dlaczego [@] nie jest tam wymagane, a nawet dozwolone? - Działa i wszystkie te szczegóły wydają się być potrzebne na podstawie moich testów, ale chciałbym zrozumieć, dlaczego!
Jan Hettich,
8
1: descTable i optsTable są po prostu przekazywane jako nazwy, więc nie ma $, będą one rozszerzane tylko w wywoływanej funkcji 2: nie do końca pewni, ale myślę, że to naprawdę nie jest konieczne 3: the! jest używane, ponieważ parametry przekazane do funkcji należy dwukrotnie rozwinąć: $ 1 rozwija się do „descTable [@]”, a to należy rozwinąć do „$ {descTable [@]}”. Składnia $ {! 1} właśnie to robi.
Elmar Zander
8
Nie sądzę, aby część „deklaruj -a” była konieczna. Istnienie nawiasów już definiuje LHS przypisania jako tablicę.
Erik Aronesty,
3
Ta odpowiedź pomogła mi rozwiązać problem właśnie teraz. Chciałem jednak zaznaczyć, że na moim komputerze (używając bash 4.3.42) „$ {! 1}” i „$ {! 2}” muszą usunąć cytaty. Jeśli tego nie zrobisz, wartość oryginalnej tablicy zostanie odczytana jako jeden ciąg i przypisana odpowiednio do argAry1 [0] i argAry2 [0], co w zasadzie oznacza utratę struktury tablicy.
user.friendly
85

Uwaga: jest to dość prymitywne rozwiązanie, które sam opublikowałem, po tym, jak nie znalazłem tutaj odpowiedzi na Przepełnienie stosu. Pozwala to na przekazanie tylko jednej tablicy i jest to ostatni element listy parametrów. Właściwie to wcale nie przekazuje tablicy, ale listę jej elementów, które są ponownie składane w tablicę przez wywołanie funkcji_funkcji (), ale działało to dla mnie. Nieco później Ken opublikował swoje rozwiązanie, ale zatrzymałem je tutaj w celu odniesienia do „historii”.

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

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

Ulepszony przez TheBonsai, dzięki.

DevSolar
źródło
19
Trzy lata po fakcie ta odpowiedź - zachowana wyłącznie ze względów historycznych - otrzymała dwie opinie negatywne w ciągu kilku dni. Jak niestety zwykle na SO, bez żadnej uwagi, dlaczego ludzie uważają, że jest to uzasadnione. Zauważ, że ta odpowiedź poprzedza wszystkie inne i że zaakceptowałem odpowiedź Kena jako najlepsze rozwiązanie. Doskonale zdaję sobie sprawę, że nie jest to prawie idealne, ale przez cztery miesiące było to najlepsze dostępne na SO. Dlaczego dwa lata po tym, jak zajął drugie miejsce, powinno być odrzucone idealne rozwiązanie Kena.
DevSolar,
@geirha: Chciałbym prosić o sprawdzenie, kto opublikował pytanie, kto opublikował tę odpowiedź i kto prawdopodobnie zaakceptował odpowiedź, którą nazywasz „złą”. ;-) Możesz także sprawdzić uwagę w pytaniu, która wskazuje, dlaczego to rozwiązanie jest gorsze od Kena.
DevSolar,
2
Wiem, że zadałeś pytanie, napisałeś tę odpowiedź i zaakceptowałeś złą odpowiedź. Dlatego sformułowałem to w ten sposób. Powodem, dla którego przyjęta odpowiedź jest zła, jest to, że próbuje przekazać tablicę przez referencję, czego naprawdę należy unikać. Ponadto przykład łączy wiele argumentów w jeden ciąg. Jeśli naprawdę potrzebujesz przekazać tablice przez referencję, bash jest niewłaściwym językiem na początek. Nawet z nowymi zmiennymi nazweref bash 4.3 nie można bezpiecznie uniknąć kolizji nazw (odwołanie cykliczne).
geirha
4
Cóż, możesz przekazać wiele tablic, jeśli podasz liczbę elementów każdej tablicy. called_function "${#array[@]}" "${array[@]}" "${#array2[@]}" "${array2[@]}"itd. ... nadal z pewnymi oczywistymi ograniczeniami, ale naprawdę lepiej jest rozwiązać problem w sposób obsługiwany przez język, niż próbować nakłonić go do działania w sposób, w jaki jesteś przyzwyczajony w innych językach.
geirha
1
@geirha: Cóż, myślę, że musimy się zgodzić, że się nie zgadzamy, a ty musisz pozwolić mi być sędzią, na który odpowiedź najlepiej odpowiada na moje pytanie. Osobiście wolę przekazywania tablic przez odniesienie i tak (bez względu na język, aby zapisać kopiując dane); tym bardziej, gdy alternatywą jest
pochylenie się
38

Komentując rozwiązanie Kena Bertelsona i odpowiadając na Jana Hetticha:

Jak to działa

takes_ary_as_arg descTable[@] optsTable[@]linii w try_with_local_arys()funkcji wysyła:

  1. To faktycznie tworzy kopię tablic descTablei, optsTablektóre są dostępne dla takes_ary_as_argfunkcji.
  2. takes_ary_as_arg()funkcja przyjmuje descTable[@]i optsTable[@]jako ciągi znaków, co oznacza $1 == descTable[@]i $2 == optsTable[@].
  3. na początku takes_ary_as_arg()funkcji używa ${!parameter}składni, która nazywa się referencją pośrednią lub czasami podwójną , co oznacza, że zamiast używać $1wartości, używamy wartości rozszerzonej wartości$1 , na przykład:

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

    podobnie dla $2.

  4. wstawienie tego argAry1=("${!1}")tworzy argAry1jako tablicę (nawiasy poniżej =) z rozwiniętym descTable[@], tak jak pisanie argAry1=("${descTable[@]}")bezpośrednio tam . declarenie jest wymagane.

Uwaga: Warto wspomnieć, że inicjalizacji tablicy za pomocą tego formularza wspornik inicjuje nową tablicę według IFSlub polowego Wewnętrznego Separator , który jest domyślnie zakładki , znak nowej linii i przestrzeni . w takim przypadku, ponieważ używał [@]notacji, każdy element jest postrzegany sam, jakby był cytowany (w przeciwieństwie do [*]).

Moja rezerwacja z tym

W BASH, zakres zmiennej lokalnej jest funkcją bieżącą i każda wywoływana z niej funkcja potomna przekłada się na fakt, że takes_ary_as_arg()funkcja „widzi” je descTable[@]i optsTable[@]tablice, a zatem działa (patrz powyższe wyjaśnienie).

W takim razie dlaczego nie spojrzeć bezpośrednio na te zmienne? To jest jak pisanie tam:

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

Zobacz powyższe objaśnienie, które po prostu kopiuje descTable[@]wartości tablicy zgodnie z bieżącym IFS.

W podsumowaniu

To w zasadzie nic nie ma wartości - jak zwykle.

Chciałbym również podkreślić powyższy komentarz Dennisa Williamsona: rzadkie tablice (tablice bez wszystkich definicji klawiszy - z „dziurami” w nich) nie będą działać zgodnie z oczekiwaniami - stracilibyśmy klucze i „kondensowali” tablicę.

Biorąc to pod uwagę, widzę wartość dla uogólnienia, funkcje mogą więc uzyskać tablice (lub kopie) bez znajomości nazw:

  • dla ~ „kopii”: ta technika jest wystarczająco dobra, wystarczy pamiętać, że wskaźniki (klucze) zniknęły.
  • dla prawdziwych kopii: możemy użyć eval dla kluczy, na przykład:

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

a następnie pętlę używającą ich do utworzenia kopii. Uwaga: tutaj !nie jest używana, to poprzednia pośrednia / podwójna ocena, ale raczej w kontekście tablicowym zwraca indeksy tablic (klucze).

  • i oczywiście, gdybyśmy mieli przekazać descTablei optsTablenapisy (bez [@]), moglibyśmy użyć samej tablicy (jak w referencji) z eval. dla ogólnej funkcji, która akceptuje tablice.
Czarodziej
źródło
2
Dobre wyjaśnienia mechanizmu wyjaśniającego Kena Bertelsona. Na pytanie „W takim przypadku, dlaczego nie spojrzeć bezpośrednio na te zmienne?”, Odpowiem: po prostu na ponowne użycie funkcji. Powiedzmy, że muszę wywołać funkcję za pomocą Array1, a następnie za pomocą Array2, przekazywanie nazw tablic staje się przydatne.
gfrigon
Świetna odpowiedź, potrzebujemy więcej takich wyjaśnień!
Édouard Lopez,
22

Podstawowym problemem jest to, że twórcy bashów, którzy zaprojektowali / zaimplementowali tablice, naprawdę spieprzyli puchata. Uznali, że ${array}to krótka ręka ${array[0]}, co było poważnym błędem. Zwłaszcza, jeśli weźmiesz pod uwagę, że ${array[0]}nie ma to znaczenia i zwraca pusty ciąg, jeśli typ tablicy jest asocjacyjny.

Przypisanie tablicy ma postać, w array=(value1 ... valueN)której wartość ma składnię [subscript]=string, tym samym przypisując wartość bezpośrednio do określonego indeksu w tablicy. To sprawia, że ​​mogą istnieć dwa typy tablic, indeksowane numerycznie i indeksowane hash (zwane tablicami asocjacyjnymi w języku bash). Dzięki temu możesz tworzyć rzadkie tablice indeksowane numerycznie. Wyjście z tej [subscript]=części jest krótką ręką dla tablicy indeksowanej numerycznie, zaczynając od porządkowego indeksu 0 i zwiększając każdą nową wartość w instrukcji przypisania.

Dlatego ${array}powinien oceniać całą tablicę, indeksy i wszystkie. Powinien być odwrócony do instrukcji przypisania. Każdy student CS-dur trzeciego roku powinien o tym wiedzieć. W takim przypadku ten kod działałby dokładnie tak, jak można się spodziewać:

declare -A foo bar
foo=${bar}

Następnie przekazywanie tablic według wartości do funkcji i przypisywanie jednej tablicy do drugiej działałoby tak, jak dyktuje reszta składni powłoki. Ale ponieważ nie zrobili tego dobrze, operator przypisania =nie działa dla tablic, a tablic nie można przekazywać wartościami do funkcji lub do podpowłok lub generalnie danych wyjściowych ( echo ${array}) bez kodu, który przejrzałby to wszystko.

Tak więc, jeśli zrobiono to dobrze, następujący przykład pokazałby, jak użyteczność tablic w bashu może być znacznie lepsza:

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

wynikowy wynik powinien wynosić:

(first=one second=2 third=3)

Następnie tablice mogłyby korzystać z operatora przypisania i być przekazywane przez wartość do funkcji, a nawet innych skryptów powłoki. Łatwo przechowywane przez wyjście do pliku i łatwe ładowanie z pliku do skryptu.

declare -A foo
read foo <file

Niestety, zawiódł nas świetny zespół programistów bash.

W związku z tym, aby przekazać tablicę do funkcji, jest tak naprawdę tylko jedna opcja, a mianowicie użycie funkcji 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

spowoduje następujące dane wyjściowe:

indexes: foo zoom
values: bar fast

Ponieważ jest to przekazywane przez odwołanie, można również przypisać tablicę w funkcji. Tak, przywoływana tablica musi mieć zasięg globalny, ale nie powinno to być zbyt duże, biorąc pod uwagę, że jest to skrypt skryptowy. Aby przekazać asocjacyjną lub rzadką tablicę indeksowaną przez wartość do funkcji, należy rzucić wszystkie indeksy i wartości na listę argumentów (nie jest to zbyt przydatne, jeśli jest to duża tablica) jako pojedyncze ciągi:

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

a następnie napisanie wiązki kodu wewnątrz funkcji w celu ponownego złożenia tablicy.

tygrys
źródło
1
Rozwiązanie użycia local -njest lepsze i bardziej aktualne niż zaakceptowana odpowiedź. To rozwiązanie będzie również działać dla zmiennej dowolnego typu. Przykład wymieniony w tej odpowiedzi można skrócić local -n ARR=${1}. Jednak -nopcja local/ declarejest dostępna tylko w wersji Bash 4.3 i nowszych.
richardjsimkins
To jest miłe! Mała gotcha: jeśli przekażesz zmienną o tej samej nazwie co lokalny argument twojej funkcji (np. funky ARR), Shell wyświetli ostrzeżenie circular name reference, ponieważ w zasadzie funkcja spróbuje to zrobić local -n ARR=ARR. Dobra dyskusja na ten temat.
Gene Pavlovsky,
5

Odpowiedź DevSolar ma jeden punkt, którego nie rozumiem (może ma konkretny powód, aby to zrobić, ale nie mogę myśleć o żadnym): Ustawia tablicę z parametrów pozycyjnych element po elemencie, iteracyjną.

Byłoby łatwiejsze podejście

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

  # now get a copy of the positional parameters
  local_array=("$@")
  ...
}
TheBonsai
źródło
1
Powodem, dla którego tego nie zrobiłem, jest fakt, że jeszcze kilka dni temu nie bawiłem się tablicami bash. Wcześniej przestawiłbym się na Perla, gdyby stał się skomplikowany, czego nie mam przy obecnej pracy. Dzięki za podpowiedź!
DevSolar
3
function aecho {
  set "$1[$2]"
  echo "${!1}"
}

Przykład

$ foo=(dog cat bird)

$ aecho foo 1
cat
Steven Penny
źródło
3

Łatwym sposobem przekazania kilku tablic jako parametru jest użycie łańcucha rozdzielanego znakami. Możesz wywołać swój skrypt w następujący sposób:

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

Następnie możesz wyodrębnić go w kodzie w następujący sposób:

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

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

W ten sposób możesz przekazać wiele tablic jako parametry i nie muszą to być ostatnie parametry.

Remy Cilia
źródło
1

Ten działa nawet ze spacjami:

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[@]}"
humbleSapiens
źródło
2
Zastanawiam się o co tu chodzi. To tylko normalne przekazywanie argumentów. Składnia „$ @” działa dla spacji: „$ @” jest równoważne z „1 $” „2 $” ...
Andreas Spindler
Czy mogę przekazać 2 tablice do funkcji?
pihentagy
1

Za pomocą kilku sztuczek możesz przekazać nazwane parametry do funkcji wraz z tablicami.

Opracowana przeze mnie metoda umożliwia dostęp do parametrów przekazywanych do funkcji takiej jak ta:

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"

Innymi słowy, nie tylko możesz wywoływać swoje parametry według ich nazw (co stanowi bardziej czytelny rdzeń), możesz faktycznie przekazywać tablice (i odniesienia do zmiennych - ta funkcja działa jednak tylko w bash 4.3)! Ponadto wszystkie zmapowane zmienne są w zasięgu lokalnym, podobnie jak 1 USD (i inne).

Kod, który sprawia, że ​​ta praca jest dość lekka i działa zarówno w bash 3, jak i bash 4 (to jedyne wersje, z którymi go testowałem). Jeśli interesuje Cię więcej takich sztuczek, które sprawiają, że programowanie w bash jest znacznie przyjemniejsze i łatwiejsze, możesz rzucić okiem na mój Bash Infinity Framework , poniższy kod został opracowany w tym celu.

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
źródło
1

Aby dodać do zaakceptowanej odpowiedzi, ponieważ znalazłem, że nie działa dobrze, jeśli zawartość tablicy jest coś takiego:

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

W takim przypadku każdy element tablicy zostaje podzielony, więc tablica, którą widzi funkcja, jest równoważna z:

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

Aby uruchomić ten przypadek, znalazłem sposób, aby przekazać nazwę zmiennej do funkcji, a następnie użyć eval:

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

function RUN_COMMANDS

Tylko moje 2 ©

AlvaroGMJ
źródło
1

Choć jest to brzydkie, oto obejście, które działa, o ile nie przekazujesz tablicy wprost, ale zmienna odpowiadająca tablicy:

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

Jestem pewien, że ktoś może wymyślić bardziej przejrzystą implementację tego pomysłu, ale uważam, że jest to lepsze rozwiązanie niż przekazywanie tablicy, "{array[@]"}a następnie uzyskiwanie do niej dostępu wewnętrznie array_inside=("$@"). Staje się to skomplikowane, gdy istnieją inne getoptsparametry pozycyjne / . W takich przypadkach musiałem najpierw określić, a następnie usunąć parametry niezwiązane z tablicą, używając kombinacji shiftusuwania elementu tablicy.

Perspektywa purystyczna prawdopodobnie postrzega to podejście jako pogwałcenie języka, ale pragmatycznie rzecz biorąc, to podejście uratowało mi wiele smutku. W pokrewnym temacie używam również evaldo przypisywania wewnętrznie skonstruowanej tablicy do zmiennej o nazwie zgodnej z parametrem target_varnameprzekazywanym do funkcji:

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

Mam nadzieję, że to komuś pomoże.

Blake Schultze
źródło
0

Wymaganie : Funkcja znajdowania ciągu w tablicy.
Jest to niewielkie uproszczenie rozwiązania DevSolar, ponieważ wykorzystuje przekazane argumenty, a nie je kopiuje.

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
źródło
0

Moja krótka odpowiedź to:

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[*]}"
Należy zauważyć, że ${test_array[*]}i ${test_array2[*]}powinny być otoczone przez „”, w przeciwnym razie zawiedziesz.

TOMMY
źródło
Twój przykład jest niepoprawny, ponieważ jest niekompletny. Podaj pełny kod skryptu.
Dennis VR,