При борьбе некоторое время передачи массива как аргумент, но это не работает так или иначе. Я попробовал как ниже:
#! /bin/bash
function copyFiles{
arr="$1"
for i in "${arr[@]}";
do
echo "$i"
done
}
array=("one" "two" "three")
copyFiles $array
Ответ с объяснением был бы хорош.
Править: В основном я в конечном счете вызову функцию из другого файла сценария. Объясните ограничения, если это возможно.
Расширение массива без индекса только дает первый элемент, использовать
copyFiles "${array[@]}"
вместо
copyFiles $array
Используйте хижину
#!/bin/bash
Используйте корректный синтаксис функций
Допустимые варианты
function copyFiles {…}
function copyFiles(){…}
function copyFiles() {…}
вместо
function copyFiles{…}
Используйте правильный синтаксис для получения параметра массива
arr=("$@")
вместо
arr="$1"
Поэтому
#!/bin/bash
function copyFiles() {
arr=("$@")
for i in "${arr[@]}";
do
echo "$i"
done
}
array=("one" "two" "three")
copyFiles "${array[@]}"
Вывод (мой сценарий имеет имя foo
)
$ ./foo
one
two
three
Вы могли также передать массив как ссылку. т.е.:
#!/bin/bash
function copyFiles {
local -n arr=$1
for i in "${arr[@]}"
do
echo "$i"
done
}
array=("one" "two" "three")
copyFiles array
, но примечание, которое любые модификации к прибытию будут сделаны выстроить.
Существует несколько проблем. Вот рабочая форма:
#!/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[@]}"
.
Здесь следует немного большему примеру. Для объяснения см. комментарии в коде.
#!/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[@]}"
Лучший способ состоит в том, чтобы передать как аргументы положения. Ничто иное. Можно передать как строка, но этот путь может доставить некоторые неприятности. Пример:
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
Вы имеете в виду, имеет ли значение массива символы пробела, необходимо заключить элементы в кавычки сначала, прежде чем передача для доступа к значению индексом в функции будет использовать $1$ 2$ 3... параметры положения. Где индекс 0-> 1, 1-> 2... Выполнить итерации доступа лучше использовать всегда 1$ и после Сдвига. Ничто дополнительное не необходимо. Можно передать аргументы без любого массива как это:
show_passed_array one two three four five
медиа удара автоматически создают массив из передаваемых аргументов, которые передали их для функционирования, и затем у Вас есть аргументы положения. Кроме того, когда Вы пишете $ {массив [2]}, Вы действительно пишете последовательный аргумент один два три четыре и передали их функции. Таким образом, те вызовы эквивалентны.
Если Вы хотите передать один или несколько аргументов И массив, я предлагаю это изменение в сценарии @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
Столь же ужасный, как это, вот обходное решение, которое работает, пока Вы не передаете массив явно, но переменную, соответствующую массиву:
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
Я передаю функции:
eval $target_varname=$"(${array_inside[@]})"
Я предлагаю избежать каких-либо ограничений на «передачу аргументов массива (ов)» в функцию с помощью ... передавая строки, и сделайте их массивом ВНУТРИ функции:
#!/bin/bash
false_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 a
echo ${a[@]}
-Himanshu