在函数Bash中:如何检查参数是否为set变量?

时间:2014-07-24 09:15:04

标签: bash variables if-statement

我想实现一个bash函数,test是第一个参数实际上是一个变量,在某处定义。

例如,在我的.bashrc

customPrompt='yes';
syntaxOn='no';
[...]
function my_func {
    [...]
    # I want to test if the string $1 is the name of a variable defined up above
    # so something like: 
    if [[ $$1 == 'yes' ]];then 
         echo "$1 is set to yes";
    else
         echo "$1 is not set or != to yes";
    fi
    # but of course $$1 doesn't work
}

需要输出:

$ my_func customPrompt
> customPrompt is set to yes
$ my_func syntaxOn
> syntaxOn is set but != to yes
$ my_func foobar
> foobar is not set

我尝试了很多测试,例如-v "$1"-z "$1"-n "$1",但所有测试都将$ 1作为字符串而不是变量。 (如果我不明白,请纠正我)

4 个答案:

答案 0 :(得分:3)

bash中,您可以使用间接变量字段。

t1=some
t2=yes
fufu() {
    case "${!1}" in
        yes) echo "$1: set to yes. Value: ${!1}";;
        '')  echo "$1: not set. Value: ${!1:-UNDEF}";;
        *)   echo "$1: set to something other than yes. Value: ${!1}";;
    esac
}

fufu t1
fufu t2
fufu t3

打印

t1: set to something other than yes. Value: some
t2: set to yes. Value: yes
t3: not set. Value: UNDEF

bash中的${!variablename}表示indirect variable expansion。在例如https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

Whrere:

  

参数扩展的基本形式是$ {parameter}。的价值   参数被替换。当参数为a时,需要括号   位置参数有多个数字,或参数是   后跟一个不被解释为其中一部分的字符   名。

     

如果参数的第一个字符是感叹号(!),则a   引入了变量间接的级别。 Bash使用的值   由参数的其余部分形成的变量作为名称   变量;然后展开此变量,并在该变量中使用该值   其余的替换,而不是参数本身的值。   这被称为间接扩张。对此的例外是   下面描述的$ {!prefix}和$ {!name [@]}的扩展。该   感叹号必须紧跟左支撑以便   介绍间接。

另外,请检查:https://stackoverflow.com/a/16131829/632407如何在函数中修改间接传递的变量的值。

答案 1 :(得分:2)

您可以像

一样检查变量集
if [[  $var ]]
then
    echo "Sorry First set variable"
else
    echo $var  
fi

您可以为脚本执行类似的操作

customPrompt='yes';
syntaxOn='no';
function my_func 
{
      if [[ ${!1} ]];then 
          echo "$1 is set to ${!1}";
      else
         echo "$1 is not set";
      fi
}
my_func customPrompt
my_func syntaxOn
my_func foobar

输出:

customPrompt is set to yes
syntaxOn is set to no
foobar is not set

您只需制作一些比较条件,即可根据您的要求自定义功能。

有关详细信息,请查看此answer

答案 2 :(得分:0)

如果你真的想检查你的变量是设置还是未设置(不只是空),请使用以下格式:

function my_func {
    if [[ -z ${!1+.} ]]; then 
         echo "$1 is not set."
    elif [[ ${!1} == yes ]]; then
         echo "$1 is set to yes"
    else
         echo "$1 is set to \"${!1}\"."
    fi
}

答案 3 :(得分:0)

你会遇到问题......

Bash shell是一个非常狡猾的生物。在执行任何操作之前,Bash会进入并插入您的命令。您的命令或shell脚本永远不会看到您是否将变量作为参数。

$ set -x
set -x
$ foo=bar
+ foo=bar
$ echo "$foo"
+ echo bar
bar
$ set +x

set -x打开shell中的调试模式。它显示了命令实际执行的内容。例如,我设置foo=bar然后执行echo $foo。我的echo命令看不到$foo。相反,在echo执行之前,使用$foo插入 bar。此时所有echo看到的是假设bar为其参数(不是$foo)。

这非常强大。这意味着您的程序不必坐在那里解释命令行。如果您输入echo *.txt,则echo不必展开*.txt,因为shell已经完成了肮脏的工作。

例如,这是一个测试shell脚本:

#! /bin/sh
if [[ $1 = "*" ]]
then
    echo "The first argument was '*'"
else
    "I was passed in $# parameters"
fi

现在,我将运行我的shell脚本:

$ test.sh *
I was passed in 24 parameters

什么?我的脚本的第一个参数不是*吗?不。shell抓取*并将其扩展为我目录中的所有文件和目录。我的shell脚本从未见过*。但是,我可以这样做:

$ test.sh '*'
The first argument was '*'

单引号告诉shell不要插入任何内容。 (双引号可防止通配,但仍允许环境变量扩展)。

如果我想查看我的第一个参数是否为变量,我必须将其传递给 引号:

$ test.sh '$foo'

而且,我可以做这个测试:

if [[ $1 != ${1#$} ]]
then
    echo "The first parameter is the variable '$1'"
fi

${1#$}看起来有点奇怪,但它只是${var#pattern}。这会从pattern的最左侧移除$var。我正在使用$1并删除$(如果存在)。这在shell中扩展为:

if [[ $foo != foo ]]

这是真的。

所以,有几件事:

  • 首先,您必须停止shell插入变量。这意味着您必须在名称周围使用单引号。
  • 您必须使用模式匹配来验证第一个参数是否以$开头。
  • 执行此操作后,您应该可以在脚本中使用${$1}变量。