在Bash中使用循环检查变量

时间:2015-09-22 12:10:26

标签: bash loops variables

我构建了一个脚本,您可以在其中设置特定文件中的变量。

现在我想编写一个检查文件中的所有变量是否为空/未设置。

以下是一个示例文件:

#variables.tmp
export foo=1
export bar=

这是我的代码,我试图找出它是否全部设置:

#!/bin/bash

PATHTOVARIABLES=/usr/local

#read variables
source $PATHTOVARIABLES/variables.tmp

#seperate comments from variables in file export.tmp
cat $PATHTOVARIABLES/variables.tmp | grep export > $PATHTOVARIABLES/export.tmp

#get variables in form "${var}"
sed -i "s/export /\"\$\{/g" $PATHTOVARIABLES/export.tmp
sed -i "s/=.*/\}\"/g" $PATHTOVARIABLES/export.tmp

#for-loop to read in variables
for i in `cat $PATHTOVARIABLES/export.tmp`
do

#check if variables are set or not
  if [ -z $i ]; then
    echo "Variable " $i " set"
  else
    echo " Variable not set"
  fi

done

rm $PATHTOVARIABLES/export.tmp

作为回报,我得到"变量未设置"变量是否设置......

我使用了我在那里找到的if条件:https://serverfault.com/questions/7503/how-to-determine-if-a-bash-variable-is-empty

你能解释我的代码有什么问题吗?我是新手来编写脚本,所以请耐心等待; - )

2 个答案:

答案 0 :(得分:1)

首先,请注意,根据定义,变量是在source命令之后设置的; bar=将变量设置为空字符串。

不需要grep或临时文件;你可以迭代 在bash中的文件上,并在读取时检查每个变量 文件。使用间接参数扩展来查找参数的值,并将其名称作为字符串。

#!/bin/bash

PATHTOVARIABLES=/usr/local

#read variables
source $PATHTOVARIABLES/variables.tmp

# Get the name of each exported value
while IFS='= ' read tag name value; do
    [[ $tag == export ]] || continue
    # Indirect expansion: get the value of
    # the parameter whose name is $name
    value=${!name}
    if [[ -z $value ]]; then
        echo "$name has empty value"
    else
       echo "$name has value ${!name}"
    fi
done < "$PATHTOVARIABLES/variables.tmp"

您可能需要考虑的一些特殊情况没有明确提及:单个export命令可以设置多个变量的值,export命令可以导出一个或者更多名称而没有实际为它们设置值。

答案 1 :(得分:-1)

PATHTOVARIABLES=/usr/local

要求对系统目录进行写访问永远不是一个好主意。我冒昧地将其重新定义为我家里的东西。

source $PATHTOVARIABLES/variables.tmp

此时,foo设置为1bar未设置。

cat $PATHTOVARIABLES/variables.tmp | grep export > $PATHTOVARIABLES/export.tmp

#get variables in form "${var}"
sed -i "s/export /\"\$\{/g" $PATHTOVARIABLES/export.tmp
sed -i "s/=.*/\}\"/g" $PATHTOVARIABLES/export.tmp

此时export.tmp包含:

"${foo}"
"${bar}"

按设计工作。

#for-loop to read in variables
for i in `cat $PATHTOVARIABLES/export.tmp`
do

此时i包含字符串"${foo}"(在第二个循环中,"${bar}")。

#check if variables are set or not
if [ -z $i ]; then

不,您正在检查变量i是否为空。它包含"${foo}",它不是空的,因此条件是假的,所以......

echo " Variable not set"

计算机完全按照你告诉他们的方式行事,而不是你想要他们做什么。 ; - )

我通过在适当的位置添加行echo $fooecho $barcat $PATHTOVARIABLES/export.tmpecho $i来解决这个问题,大大缩小了脚本停止满足您期望的位置。你可以自己完成这个,给出一个更短的问题......

如果您正在寻找一种方法来检查是否设置了i中名为的变量然后您要查找的命令为eval(警告警告如下)。

for i in `cat $PATHTOVARIABLES/export.tmp`
do
    eval "tmp=${i}"    # expands to tmp="${foo}" / tmp="${bar}" and gets evaluated

    if [[ -z $tmp ]]
    then
        echo "Variable ${i} is not set."
    else
        echo "Variable ${i} is set to ${tmp}."
    fi
done

<强>注意:

在外部输入上使用eval 有潜在危险。如果攻击者能够修改脚本向eval提供的任何内容(在本例中为文件variables.tmp),那么他可以使用任何正在执行的用户的权限执行命令脚本(在您的情况下,root - 这就是为什么测试root的东西不是一个好主意。)

我无法看到这种情况可能会发生在您的具体案例中,但我问用户chepner,他似乎不同意。