Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何将多个参数(包括数组)传递给Bash中未定义顺序且数组元素可以有多个单词的函数?_Arrays_Bash_Function_Parameters_Variable Expansion - Fatal编程技术网

Arrays 如何将多个参数(包括数组)传递给Bash中未定义顺序且数组元素可以有多个单词的函数?

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“备

我花了好几个小时想弄明白这一点

我想做的是有一个函数,可以接收N参数,其中可以包括数组

数组可以位于任何参数位置,而不仅仅是最后一个

参数的顺序可以更改,例如,我可以一次将第一个参数作为数组传递,另一次将其作为第二个参数传递

阵列和常规参数必须可互换

示例代码(注意,本示例中的参数顺序是固定的,有关问题,请参见以下示例):

#$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/”
传递,并将其作为
分隔

如何解决第二个示例,其中顺序或参数可能会发生变化

如何解决第二个示例,其中顺序或参数可能会发生变化

有两种通用的独立于编程语言的解决方案,可以将任何程序员都应该知道的可变长度的项目列表连接在一起:

  • 通过计数
  • 使用一个
  • 我看到了两种特定于bash的解决方案:

  • 将数组作为名称传递并使用名称引用
  • 像真正的男人一样分析论点。这实际上是一个通用的解决方案,因为它通常在创建参数列表时执行数据,然后在读取参数时执行数据反序列化-格式(参数作为选项)特定于shell
  • 通常,如果函数有常量和少量参数,只需使用参数即可。如果函数因更多的边缘情况而变得复杂,我建议像解析人一样解析参数——使函数具有通用性和抽象性,易于扩展和实现边缘情况,易于处理角落情况和错误,易于其他程序员理解,易于人眼阅读和分析

    因为您的示例代码可能存在一些问题,我建议研究引用在Shell中是如何工作的,特别是
    “${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[@]}"