1

在解释我的 bash 问题之前,让我给你一些背景信息:

我正在使用我们在当前工作中使用的 bash“框架”编写一些脚本。该框架的一个特点是初始化一组环境变量,这些变量对在我们的集群基础设施上运行作业很有用。

这些变量取决于由 指定的日期$YY,它们也是环境变量(是的,这是连线的)$mm$dd要使用该框架,您首先定义日期,然后调用一个函数来初始化其他变量。当您编写仅需要特定日期变量的脚本时,这可以正常工作。今天我正在写一些需要变量 2 天的东西。写这篇我面临一个奇怪的问题。为了让您更好地理解问题,我编写了这段代码来模拟它:

#!/bin/bash

function assign(){
    date=$1
    date[1]=$YY
    date[2]=$mm
    date[3]=$dd
}

function display() {
    date=$1
    echo "${date[1]}/${date[2]}/${date[3]}"
}

export YY=2012
export mm=09
export dd=20
declare -a my_date1=()
assign $my_date1

export YY=2012
export mm=08
export dd=20
declare -a my_date2=()
assign $my_date2

display $my_date1
display $my_date2

预期的输出是:

2012/09/20
2012/08/20

但输出是:

2012/08/20
2012/08/20

起初我认为 assign 函数使用引用填充数组$YY$mm$dd不是它们的值。但后来我尝试使用以下代码,它不会改变结果。

date[1]=$(echo $YY)
date[2]=$(echo $mm)
date[3]=$(echo $dd)

有人可以解释一下附加什么吗?也许有些东西与date=$1......

4

1 回答 1

3

在 bash 中,数组不是通过值或引用传递的。相反,数组的扩展值是按值传递的。当你写

assign $my_date1

里面的date变量assign是空的,因为$my_date1在调用函数之前扩展为空字符串并在分词后消失。结果,$1未设置。

但是,作为一个全局变量,因为它没有被声明为本地,所以使用et aldate正确设置然后在第二次调用.YYassign

另外,请注意,函数的第一行没有date引用参数;它实际上只是将成为全局date数组的第 0 个元素设置为$1.


话虽如此,我将向您展示一种使用declare内置和间接参数扩展来伪造它的方法。

function assign () {
    ref=$1
    # Without the -g, we'd declare function-local parameters. The argument is a
    # string to evaluate as a variable assignment. If $ref=my_date1, then we do
    # 'my_date1[1]=$YY', 'my_date1[2]=$mm', etc.
    declare -g "$ref[1]=$YY"
    declare -g "$ref[2]=$mm"
    declare -g "$ref[3]=$dd"
}

function display () {
    ref=$1
    # If $ref=my_date1, then idx
    # iterates over my_date[1], my_date[2], my_date[3].
    # E.g. ${!idx} in the first iteration is ${my_date[1]}.
    arr=()
    for idx in $ref[{1,2,3}]; do
        arr+=( ${!idx} )
    done
    local IFS="/"
    echo "${arr[*]}"
}

export YY=2012 mm=09 dd=20
assign my_date1    # The *name* of the array; no need to predeclare

export YY=2012 mm=08 dd=20
assign my_date2    # The *name* of the array; no need to predeclare

# Again, just the *names* of the arrays
display my_date1
display my_date2
于 2012-09-21T19:22:34.873 回答