【问题标题】:Pass a combination of arguments and array from a linux shell script to another shell script将参数和数组的组合从 linux shell 脚本传递到另一个 shell 脚本
【发布时间】:2024-01-06 15:19:01
【问题描述】:

如何将以下 2 个变量和数组(每次尺寸都会不同)从 linux shell 脚本传递到另一个 shell 脚本?

logfolder=mylogfolder
processname=myname

script=(\
[1]="1 MyScript1" \
[2]="2 MyScript2 MyScript3 MyScript4 MyScript5 MyScript6 MyScript7 MyScript8 MyScript9 MyScript10 MyScript11" \
[3]="2 MyScript12 MyScript13" \
[4]="2 MyScript14 MyScript15" \
[5]="1 MyScript16" \
[6]="1 MyScript17")

【问题讨论】:

    标签: arrays linux bash shell arguments


    【解决方案1】:

    您需要只传递数组的元素,还是特定的索引->元素映射?我问的原因是您提供的示例数组的索引为 1-6,但默认情况下,bash 数组的索引为 0-5。我将假设索引并不重要(除了顺序);如果需要通过,事情会变得有点复杂。

    有两种相当标准的方法可以做到这一点;您可以将两个固定参数作为前两个位置参数($1$2)传递,并将数组作为第三个传递,如下所示:

    #!/bin/bash
    # Usage example:
    #    ./scriptname "mylogfolder" "myname" "1 MyScript1" \
    #        "2 MyScript2 MyScript3 MyScript4 MyScript5 MyScript6 MyScript7 MyScript8 MyScript9 MyScript10 MyScript11" \
    #        "2 MyScript12 MyScript13" ...
    logfolder=$1
    processname=$2
    script=("${@:3}")
    

    或者,如果这两个值是可选的,您可以将它们设为带参数的选项,如下所示:

    #!/bin/bash
    # Usage example:
    #    ./scriptname -l "mylogfolder" -p "myname" "1 MyScript1" \
    #        "2 MyScript2 MyScript3 MyScript4 MyScript5 MyScript6 MyScript7 MyScript8 MyScript9 MyScript10 MyScript11" \
    #        "2 MyScript12 MyScript13" ...
    
    while getopts "l:p:" o; do
        case "${o}" in
            l)
                logfolder =${OPTARG} ;;
            p)
                processname =${OPTARG} ;;
            *)
                echo "Usage: $0 [-l logfolder] [-p processname] script [script...]" >&2
                exit 1
                ;;
        esac
    done
    shift $((OPTIND-1))
    
    script=("${@}")
    

    在任何一种情况下,要传递一个数组,您都需要使用 "${arrayname[@]}" 将每个元素作为单独的参数传递给脚本。

    [编辑] 传递数组索引 with 元素更复杂,因为 arg 列表基本上只是一个字符串列表。您需要以某种方式对索引和元素进行编码,然后在脚本中将它们解析出来。这是一种方法,对数组中的每个事物使用index=element

    #!/bin/bash
    # Usage example:
    #    ./scriptname "mylogfolder" "myname" "1=1 MyScript1" \
    #        "2=2 MyScript2 MyScript3 MyScript4 MyScript5 MyScript6 MyScript7 MyScript8 MyScript9 MyScript10 MyScript11" \
    #        "3=2 MyScript12 MyScript13" ...
    
    logfolder=$1
    processname=$2
    # Parse arguments 3 on as index=element pairs:
    declare -a script=()
    for scriptarg in "${@:3}"; do
        index=${scriptarg%%=*}
        if [[ "$index" = "$scriptarg" || -z "$index" || "$index" = *[^0-9]* ]]; then
            echo "$0: invalid script array index in '$scriptarg'" >&2
            exit 1
        fi
        script[$index]=${scriptarg#*=}
    done
    

    要调用它,您需要以适当的格式打包脚本数组,如下所示:

    # Convert the normal script array to a version that has "index=" prefixes
    scriptargs=()
    for index in "${!script[@]}"; do    # iterate over the array _indexes_
        scriptargs+=("${index}=${script[$index]}")
    done
    
    ./script.sh "$logfolder" "$processname" "${scriptargs[@]}"
    

    【讨论】:

    • 我实际上将脚本数组用作二维数组,因此 [1] 到 [6] 并且它们的值必须在接收脚本中以正确的顺序解包。这将是传递给脚本的唯一数组,它可以是开始的第三个参数和最后一个参数,但它的两个维度都是可变的。