Как передать массив как аргумент функции?

Борьба в течение некоторого времени, передавая массив как аргумент, но он все равно не работает. Я пробовал, как показано ниже:

#! /bin/bash

function copyFiles{
   arr="$1"
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")

copyFiles $array

Ответ с объяснением был бы приятным.

Изменить: В принципе, я в конечном итоге вызову функцию из другого файла сценария. Plz объясняет, по возможности, ограничения.

1
задан 15 September 2015 в 11:50

10 ответов

Вы также можете передать массив в качестве ссылки. то есть: ^!d0]

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

, но обратите внимание, что любые изменения в arr будут сделаны для массива.

5
ответ дан 23 May 2018 в 17:27
  • 1
    Хотя, это было не совсем то, что я хочу, но мне все же приятно знать, как проходит эталонная работа в bash. +1 :) – Ahsanul Haque 15 September 2015 в 15:27

Есть пара проблем. Вот рабочая форма:

#!/bin/bash
function copyFiles {
   arr=( "$@" )
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")
copyFiles "${array[@]}"
Должно быть хотя бы пробел между объявлением функции и {. Вы не можете использовать $array, так как array - массив, а не переменная. Если вы хотите получить все значения массива, используйте "${array[@]}". В объявлении основной функции вам нужно arr="$@", поскольку "${array[@]}" будет расширяться до индексированных значений, разделенных пробелами, если вы используете $1, вы получите только первое значение. Для получения всех значений используйте arr="$arr[@]}".
4
ответ дан 23 May 2018 в 17:27
  • 1
    Вам нужно arr=("$@") – A.B. 15 September 2015 в 12:38
  • 2
    Чтобы увидеть разницу, добавьте break ниже echo "$i". В вашей версии вы все равно увидите все элементы. Однако это должно быть три строки. – A.B. 15 September 2015 в 12:43
  • 3
    @ A.B. Мой плохой ... спасибо .. я его не проверял ... просто напиши это из моей головы .... отредактировал .. – heemayl 15 September 2015 в 12:59
  • 4
    @heemayl: маленькая опечатка - {в вашем массиве второй пули пропало ... " $ {array [@]} " ... – Cbhihe 15 September 2015 в 20:36
  • 5
    @Cbhihe спасибо .. исправлено .. – heemayl 15 September 2015 в 20:43

Здесь следует несколько больший пример. Для пояснения см. Комментарии в коде.

#!/bin/bash -u
# ==============================================================================
# Description
# -----------
# Show the content of an array by displaying each element separated by a
# vertical bar (|).
#
# Arg Description
# --- -----------
# 1   The array
# ==============================================================================
show_array()
{
    declare -a arr=("${@}")
    declare -i len=${#arr[@]}
    # Show passed array
    for ((n = 0; n < len; n++))
    do
        echo -en "|${arr[$n]}"
    done
    echo "|"
}

# ==============================================================================
# Description
# -----------
# This function takes two arrays as arguments together with their sizes and a
# name of an array which should be created and returned from this function.
#
# Arg Description
# --- -----------
# 1   Length of first array
# 2   First array
# 3   Length of second array
# 4   Second array
# 5   Name of returned array
# ==============================================================================
array_demo()
{
    declare -a argv=("${@}")                           # All arguments in one big array
    declare -i len_1=${argv[0]}                        # Length of first array passad
    declare -a arr_1=("${argv[@]:1:$len_1}")           # First array
    declare -i len_2=${argv[(len_1 + 1)]}              # Length of second array passad
    declare -a arr_2=("${argv[@]:(len_1 + 2):$len_2}") # Second array
    declare -i totlen=${#argv[@]}                      # Length of argv array (len_1+len_2+2)
    declare __ret_array_name=${argv[(totlen - 1)]}     # Name of array to be returned

    # Show passed arrays
    echo -en "Array 1: "; show_array "${arr_1[@]}"
    echo -en "Array 2: "; show_array "${arr_2[@]}"

    # Create array to be returned with given name (by concatenating passed arrays in opposite order)
    eval ${__ret_array_name}='("${arr_2[@]}" "${arr_1[@]}")'
}

########################
##### Demo program #####
########################
declare -a array_1=(Only 1 word @ the time)                                       # 6 elements
declare -a array_2=("Space separated words," sometimes using "string paretheses") # 4 elements
declare -a my_out # Will contain output from array_demo()

# A: Length of array_1
# B: First array, not necessary with string parentheses here
# C: Length of array_2
# D: Second array, necessary with string parentheses here
# E: Name of array that should be returned from function.
#          A              B             C              D               E
array_demo ${#array_1[@]} ${array_1[@]} ${#array_2[@]} "${array_2[@]}" my_out

# Show that array_demo really returned specified array in my_out:
echo -en "Returns: "; show_array "${my_out[@]}"
2
ответ дан 23 May 2018 в 17:27

Если вы хотите передать один или несколько аргументов и массив, я предлагаю это изменение скрипту @ A.B. Массив должен быть последним аргументом, и только один массив может быть передан

#!/bin/bash
function copyFiles() {
   local msg="$1"   # Save first argument in a variable
   shift            # Shift all arguments to the left (original $1 gets lost)
   local arr=("$@") # Rebuild the array with rest of arguments
   for i in "${arr[@]}";
      do
          echo "$msg $i"
      done
}

array=("one" "two" "three")

copyFiles "Copying" "${array[@]}"

Выход:

$ ./foo   
Copying one
Copying two
Copying three
2
ответ дан 23 May 2018 в 17:27

Лучший способ - передать аргументы позиции. Ничего больше. Вы можете передать строку, но этот способ может вызвать некоторые проблемы. Пример:

array=(one two three four five)

function show_passed_array(){
  echo $@
}

или

function show_passed_array(){
  while $# -gt 0;do
    echo $1;shift
  done
}

    show_passed_array ${array[@]}

output:

  one two three four five

Вы имеете в виду, что если значение массива имеет пробельные символы, вы должны сначала процитировать элементы перед прохождением для доступа к значению по индексу в функции используйте параметры позиции $ 1 $ 2 $ 3 .... Где индекс 0 -> 1, 1 -> 2, ... Для итерации доступа лучше всего использовать $ 1 и после Shift. Ничего дополнительного не требуется. Вы можете передавать аргументы без такого массива:

show_passed_array one two three four five

bash media автоматически создает массив из переданных аргументов, которые передавали их функции, а затем у вас есть аргументы позиции. Кроме того, когда вы пишете $ {array [2]}, вы действительно записываете последовательный аргумент один два три четыре и передавали их функции. Таким образом, эти призывы эквивалентны.

0
ответ дан 23 May 2018 в 17:27

Вы также можете передать массив в качестве ссылки. то есть: ^!d0]

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

, но обратите внимание, что любые изменения в arr будут сделаны для массива.

5
ответ дан 23 May 2018 в 17:27

Вы также можете передать массив в качестве ссылки. то есть: ^!d0]

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

, но обратите внимание, что любые изменения в arr будут сделаны для массива.

5
ответ дан 23 May 2018 в 17:27

Вы также можете передать массив в качестве ссылки. то есть: ^!d0]

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

, но обратите внимание, что любые изменения в arr будут сделаны для массива.

5
ответ дан 23 May 2018 в 17:27

Вы также можете передать массив в качестве ссылки. то есть: ^!d0]

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

, но обратите внимание, что любые изменения в arr будут сделаны для массива.

5
ответ дан 23 May 2018 в 17:27

Вы также можете передать массив в качестве ссылки. то есть: ^!d0]

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

, но обратите внимание, что любые изменения в arr будут сделаны для массива.

5
ответ дан 23 May 2018 в 17:27

Другие вопросы по тегам:

Похожие вопросы: