Arrays 如何将多个参数(包括数组)传递给Bash中未定义顺序且数组元素可以有多个单词的函数?
我花了好几个小时想弄明白这一点 我想做的是有一个函数,可以接收N参数,其中可以包括数组 数组可以位于任何参数位置,而不仅仅是最后一个强> 参数的顺序可以更改,例如,我可以一次将第一个参数作为数组传递,另一次将其作为第二个参数传递强> 阵列和常规参数必须可互换强> 示例代码(注意,本示例中的参数顺序是固定的,有关问题,请参见以下示例):Arrays 如何将多个参数(包括数组)传递给Bash中未定义顺序且数组元素可以有多个单词的函数?,arrays,bash,function,parameters,variable-expansion,Arrays,Bash,Function,Parameters,Variable Expansion,我花了好几个小时想弄明白这一点 我想做的是有一个函数,可以接收N参数,其中可以包括数组 数组可以位于任何参数位置,而不仅仅是最后一个 参数的顺序可以更改,例如,我可以一次将第一个参数作为数组传递,另一次将其作为第二个参数传递 阵列和常规参数必须可互换 示例代码(注意,本示例中的参数顺序是固定的,有关问题,请参见以下示例): #$1菜单标题 #$2菜单选项列表 #$3菜单文本 菜单(){ 对话框--清除--标准输出--标题“$1”--菜单“$3”0“$2” } 选择权=( 1“备选方案1” 2“备
#$1菜单标题
#$2菜单选项列表
#$3菜单文本
菜单(){
对话框--清除--标准输出--标题“$1”--菜单“$3”0“$2”
}
选择权=(
1“备选方案1”
2“备选方案2”
3“备选方案3”
4“备选方案4”)
菜单“标题”${options[@]}“文本”
第一个例子可以这样解决:
#$1菜单标题
#$2菜单选项列表
#$3菜单文本
菜单(){
本地-不适用=2美元
对话框--清除--标准输出--标题“$1”--菜单“$3”0“${a[@]}”
}
选择权=(
1“备选方案1”
2“备选方案2”
3“备选方案3”
4“备选方案4”)
菜单“标题”选项“文本”
问题示例:
my_func(){
我的命令“$1”--某物“$2”$3”--某物“$4”
}
选择A=(
1“备选方案1”
2“备选方案2”
3“备选方案3”
4“备选方案4”)
选项b=(
1“备选方案1”
2“备选方案2”
3“备选方案3”
4“备选方案4”)
my_func“Title”${optionsa[@]}“Text”${optionsb[@]}
#请注意,我可以做到这一点,它也必须工作:
my_func${optionsa[@]}“标题”${optionsb[@]}“文本”
#这也必须起作用:
my_func${optionsa[@]}${optionsb[@]}“标题”文本
当数组展开时,必须能够使用这些值作为命令的参数,如果数组中的值引用了多个字(“选项1”),则必须将其视为单个参数,以避免将路径作为“/my dir/”
传递,并将其作为
分隔
如何解决第二个示例,其中顺序或参数可能会发生变化
如何解决第二个示例,其中顺序或参数可能会发生变化
有两种通用的独立于编程语言的解决方案,可以将任何程序员都应该知道的可变长度的项目列表连接在一起:
“${array[@]}”与${array[@]}
的区别,研究[@]
与[*]
的区别,执行分词扩展的方式和时间,以及它对参数的影响。代码中所有不带引号的数组扩展都会受到单词拆分的影响——在第一个示例中,空格也不会被保留
my_func() {
local tmp optionsa title text optionsb
tmp=$1
shift
while ((tmp--)); do
optionsa+=("$1")
shift
done
title="$1"
shift
tmp=$1
shift
while ((tmp--)); do
optionsb+=("$1")
shift
done
text=$1
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func 0 "Title" 0 "Text"
my_func 0 "Title" "${#optionsb[@]}" "${optionsb[@]}" "Text"
my_func "${#optionsa[@]}" "${optionsa[@]}" "Title" "${#optionsb[@]}" "${optionsb[@]}" "Text"
my_func() {
local tmp optionsa title text optionsb
while [[ -n "$1" ]]; do
optionsa+=("$1")
shift
done
title=$1
shift
while [[ -n "$1" ]]; do
optionsb+=("$1")
shift
done
text=$1
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func "" "Title" "" "Text"
my_func "" "Title" "${optionsb[@]}" "" "Text"
my_func "${optionsa[@]}" "" "Title" "${optionsb[@]}" "" "Text"
my_func() {
# Use unique names to avoid nameclashes
declare -n _my_func_optionsa=$1
local title=$2
declare -n _my_func_optionsb=$3
local title=$4
my_command "${_my_func_optionsa[@]}" "$title" "${_my_func_optionsb[@]}" "$text"
}
# arrays have to exists
my_func optionsa "Title" optionsb "Text"
my_func() {
local args
# I am used to linux getopt, getopts would work as well
if ! args=$(getopt -n "$my_func" -o "a:t:b:x:" -- "$@"); then
echo "my_func: Invalid arguments" >&2
return 1
fi
set -- "$args"
local optionsa title optionsb text
while (($#)); do
case "$1" in
-a) optionsa+=("$2"); shift; ;;
-t) title="$2"; shift; ;;
-b) optionsb+=("$2"); shift; ;;
-x) text="$2"; shift; ;;
*) echo "my_func: Error parsing argument: $1" >&2; return 1; ;;
esac
shift
done
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func -a opta1 -a opta2 -t Title -b optb1 -b optb2 -x text
# or build the options list from arrays:
# ie. perform data serialization
args=()
for i in "${optionsa[@]}"; do
args+=(-a "$i")
done
args+=(-t "title")
for i in "${optionsb[@]}"; do args+=(-b "$i"); done
args+=(-x "text")
my_func "${args[@]}"