关于返回值的全局变量与局部变量赋值的看似语义差异

时间:2017-06-04 20:33:10

标签: bash shell

给出以下bash脚本:

#!/usr/bin/env bash

echo $BASH_VERSION

# local [option] [name[=value] ... | - ]
#   For each argument, a local variable named name is created, and assigned value.  The option can  be  any
#   of  the options accepted by declare.  When local is used within a function, it causes the variable name
#   to have a visible scope restricted to that function and its children.  If name is -, the set  of  shell
#   options  is  made  local to the function in which local is invoked: shell options changed using the set
#   builtin inside the function are restored to their original values when the function returns.   With  no
#   operands,  local  writes a list of local variables to the standard output.  It is an error to use local
#   when not within a function.  The return status is 0 unless local is used outside a function, an invalid
#   name is supplied, or name is a readonly variable.

function __count_words {
    local feedback=$(echo "app1 app2")
    echo $feedback
    return $(IFS=' ' set -- ${feedback} && echo $#)
}

function invoke_func {
    declare -f $1_${DF_SYSTEM} >/dev/null
    [ $? -eq 0 ] && { $1_${DF_SYSTEM}; return $?; } || { $1; return $?; }
}

function check_words {
    local list=$(invoke_func __count_words)
    local count=$?
    echo "V1: XXXX [c=$count] > $list"
    list2=$(invoke_func __count_words)
    local count2=$?
    echo "V2: XXXX [c=$count2] > $list2"
}

check_words

输出结果为:

4.4.12(1)-release
V1: XXXX [c=0] > app1 app2
V2: XXXX [c=2] > app1 app2

决定在返回值方面做出看似相似的赋值语法的原因是什么?我估计我找到了bash(1)手册页的相关部分,但不清楚为什么这样做是这样的。

在局部变量赋值的情况下,返回状态始终为0,但是对于全局赋值,返回状态根据赋值内被调用函数的返回状态而变化。

1 个答案:

答案 0 :(得分:2)

这是Shellcheck检测为SC2155的问题;考虑阅读链接的维基页面(也许,通过Shellcheck运行您的代码,然后再在此处询问)。

check_words功能的最佳实践实现如下所示,展示您的问题:

check_words() {
    local list count count2               # intentionally leaving list2 global
    list=$(invoke_func __count_words)
    count=$?
    echo "V1: XXXX [c=$count] > $list"
    list2=$(invoke_func __count_words)
    count2=$?
    echo "V2: XXXX [c=$count2] > $list2"
}

local关键字是内置命令。与其他命令一样,它具有退出状态。因此,该退出状态将覆盖用于派生值的命令替换的任何退出状态。

(另外,function关键字使您的代码无意义地与POSIX sh不兼容,同时不添加任何补偿优势;最好避免使用符合POSIX的函数声明语法。