Если вы хотите передать один или несколько аргументов И массив, я предлагаю это изменение в скрипте @A.B. Массив должен быть последний аргумент и единственный массив может быть передан
#!/bin/bashfunction 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[@]}"
#!/bin/bashfunction copyFiles { arr=( "$@" ) for i in "${arr[@]}"; do echo "$i" done}array=("one" "two" "three")copyFiles "${array[@]}"
Между объявлением функции и {
Вы не можете использовать $array, как array это массив, а не переменная. Если вы хотите получить все значения массива, используйте "${array[@]}"
В вашем объявлении основной функции вам нужно arr="$@" как "${array[@]}" будет расширен до индексированных значений, разделенных пробелами, если вы используете $1 вы получите только первое значение. Чтобы получить все значения, используйте arr="${arr[@]}".
Далее следует немного более крупный пример. Пояснения см. в комментариях к коду.
#!/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 elementsdeclare -a array_2=("Space separated words," sometimes using "string paretheses") # 4 elementsdeclare -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 Earray_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[@]}"
Лучший способ - передать в качестве аргументов позиции. Ничего больше. Вы можете передать как строку, но этот способ может вызвать некоторые проблемы. Пример:
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[@]}
выход:
one two three four five
>>Вы имеете в виду, что если значение массива содержит символы пробела, вы должны сначала заключить элементы в кавычки перед передачей для доступа к значению по индексу в функции use $1 $2 $ 3 ... position parameters. Где индекс 0 - 1, 1 - 2,... Для итерации доступа лучше всего использовать всегда $ 1 и после сдвига. Ничего дополнительного не требуется. Вы можете передавать аргументы без какого-либо массива, подобного этому:
show_passed_array one two three four five
bash media автоматически создает массив из переданных аргументов, который передает их в функцию, а затем у вас есть аргументы позиции.Кроме того, когда вы пишете ${array[2]}, вы действительно записываете последовательный аргумент один, два, три, четыре и передаете их функции.Так что эти вызовы эквивалентны.
Каким бы уродливым это ни было, вот обходной путь, который работает до тех пор, пока вы явно передаете не массив, а переменную, соответствующую массиву:
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
Я уверен, что кто-то может придумать более чистую реализацию этой идеи, но я обнаружил, что это лучшее решение, чем передача массива в виде "{array[@]"} а затем получить к нему внутренний доступ с помощью array_inside=("$@"). Это усложняется, когда существуют другие позиционные/getopts параметры. В этих случаях мне приходилось сначала определять, а затем удалять параметры, не связанные с массивом, используя некоторую комбинацию shift и удаление элементов массива.
С точки зрения пуристов, вероятно, такой подход рассматривается как нарушение языка, но с прагматической точки зрения этот подход избавил меня от множества огорчений. По смежной теме я также использую eval чтобы присвоить внутренне созданный массив переменной, названной в соответствии с параметром target_varname Я перехожу к функции:
Я предлагаю избежать каких-либо ограничений в отношении "передачи аргументов массива (ов)" в функцию путем ... передачи строк и превращения их в массив ВНУТРИ функции :
#!/bin/bashfalse_array1='1 2 3 4 5'false_array2='my super fake array to deceive my function'my_normal_string='John'function i_love_arrays(){ local myNumbers=("$1") local mySentence=("$2") local myName="$3" echo "My favorite numbers are, for sure: " for number in ${myNumbers[@]} do echo $number done echo "Let's make an ugly split of a sentence: " for word in ${mySentence[@]} do echo $word done echo "Yeah, I know, glad to meet you too. I'm ${myName}."}i_love_arrays "${false_array1}" "${false_array2}" "${my_normal_string}"
Использование ссылок (самый простой способ; лучший и единственный способ передачи ассоциативные массивы):
print(){ [ "$1" = "arr" ] || { declare -n arr; arr="$1"; } # The name of reference mustn't match the input coming to the function. # If it does, use the name directly as array instead of reference. echo "${arr[@]}"}print arr
Для нормального (неассоциативный) массивы:
Вот функция, которая копирует переданный массив в новый (локальный) массив для использования. Может занять много времени для длинных массивов.
copy_fn(){ eval local newarr=\(\${$1[@]}\) echo ${newarr[@]}}
Кроме того, как и в C++, вы можете передавать только указатель на массив, но в python в качестве общей переменной, которую вы также можете изменять.
Вот подход с общими переменными .. полезный для длинных массивов.
modify_arr(){ eval local ptr=$1 # works as if ptr is a pointer to actual "array-name" (arr) # the original array is, thus, still same, not a copy eval $ptr+=(1) # modify the array echo ${ptr[@]} # will print name of the array (arr) eval echo \$\{$ptr[@]\} # will print the actual array (arr)}modify_arr aecho ${a[@]}
Ваша идея вызвала некоторые размышления о ситуации, в которой я нуждался, когда нужно было сравнить два массива.
Вы можете передавать несколько массивов, используя свою технику с небольшими изменениями. Смотреть ниже
Спасибо!
(работает в bash 3.3 на Debian)
#!/bin/bash#function TakeTwoArrays() { local Var1="$1" local Var2="$2" local NumArray1="$3" local NumArray2="$4" shift 4 local -a AllArray=("$@") local -a Array1="${AllArray[@]:0:${NumArray1}}" local -a Array2="${AllArray[@]:${NumArray1}}" echo "Var1 is ${Var1}" echo "Var2 is ${Var2}" echo "Array1 has ${NumArray1} entries:" printf '%s\n' "${Array1[@]}" echo "Array2 has ${NumArray2} entries:" printf '%s\n' "${Array2[@]}"}FirstArg="So Far"SecondArg="So Good"Array1Arg=("But" "the" "real" "question" "is")NumArray1Arg="${#Array1Arg[@]}"Array2Arg=("What" "happens" "with" "the" "second" "set" "of" "elements")NumArray2Arg="${#Array2Arg[@]}"TakeTwoArrays "${FirstArg}" "${SecondArg}" "${NumArray1Arg}" "${NumArray2Arg}" "${Array1Arg[@]}" "${Array2Arg[@]}"