设置一个局部变量,使其值保持在shell函数中的多个调用之间

时间:2017-12-20 16:52:20

标签: bash

我正在寻找最佳解决方案。我想在函数中使用局部变量,因此忽略在调用函数之前声明的全局变量。

示例:

username="niquit"

User() {
local parsedoptions=$( getopt -q -n "$0" -o u: -- "$@" )
eval set -- "$parsedoptions"

while :
do
    case "$1" in
    -u)
        if [[ $2 ]]
        then
            local username=$2
        fi

        shift 2;;
    --)
        shift

        break;;
    esac
done

if [[ $username ]]
then
    echo "Error"
else
    local username="test"
fi
}

 User -u test

我当然可以使用更改User_username函数中的变量名称,或者在函数开始时取消设置所有打结的局部变量,但我想跳过这些解决方案。

1 个答案:

答案 0 :(得分:3)

使用Namevars模拟静态变量

常规函数范围的局部变量在任何广泛使用的编程语言中对函数的多次调用都不会保留它们的值(如果默认情况下存在此属性,则编写可重入代码将更加困难 - 即函数可以安全地递归使用)。在具有这些行为的语言中,具有此行为的变量称为"静态变量"。

Bash本身不支持静态变量。

作为一种解决方法,请考虑一个包含函数名称的全局变量命名约定 - 与namevar结合使用,可以通过所需的更短的本地名称引用这些全局变量:

User() {
  declare -g User__username
  local -n username=User__username  ## NOTE: THIS REQUIRES BASH 4.3 OR NEWER

  if [[ $username ]]; then
    echo "OK: Already set to $username"
  else
    username=test
  fi

  echo "$username"
}

原始问题:关于局部变量

本地变量在声明本地变量之前不是本地变量。您需要将该声明放在函数的顶部:

User() {
    local username
    if [[ $username ]]; then
      echo "FAILED: Non-local variables should never be visible"
    else
      username="test"
    fi
    echo "$username"
}

local var=whatever也是出于其他原因的错误做法:如果您运行var=$(something),则退出状态将反映something是否成功,但如果您运行local var=$(something),则它反映了local是否成功,放弃了something的退出状态。