我有很多变量var1 var2 ... varx
,可能是空的,也可能不是。我不想有多个if
语句,并且想知道如何创建一个循环,我提供了一个变量列表,并检查它们是否为空。如果变量为空,则其值应设置为-
答案 0 :(得分:1)
这会让您进入eval
领域:
for var in var1 var2 varx; do
eval 'val=$'"$var"
if [ -z "$val" ]; then
eval "${var}=-"
fi
done
请注意,任何可以提供任意变量名称的源都可以滥用它来运行任意代码;确保您仅在上述情况下使用它,var
的价值由您控制。
答案 1 :(得分:1)
正如@ hek2mgl首次提到的那样,如果变量尚未具有
的值,则可以为变量赋值。: ${var1:=--}
: ${var2:=--}
: ${var3:=--}
# etc
请注意,这比循环占用的空间更多,但它更具可读性,因为它不需要任何间接解密。
答案 2 :(得分:0)
我通过创建一个数组arr
来解决它,而不是使用多个变量,迭代数组的元素并用--
替换空的
for element in "${!arr[@]}"; do
out[$element]=${out[$element]:---}
done
答案 3 :(得分:0)
Bash允许您对变量名称进行递归替换,因此您可以使用${var${suffix}}
之类的内容,但sh(1)
不会,因此您必须使用eval
表达式来允许延迟变量扩展,如:
#!/bin/sh
TEMPFILE="/tmp/defaults.sh-$$"
trap 'rm -f "$TEMPFILE"' 1 2 3 15
# FORMAT IS FIRST WORD IS VARIABLE NAME, REST OF LINE IF DEFAULT VALUE.
cat > "$TEMPFILE" << EOF
A default value for variable A
B default value for variable B
C default value for variable C
PATH /bin:/usr/bin
HOME $HOME
EOF
while read name value
do
eval echo "$name==\$$name"
if
[ -z "`eval echo \\\$$name`" ]
then
echo "$name=\"$value\""
eval "$name=\"$value\""
fi
done <"$TEMPFILE"
while read name dumb
do
eval echo "[$name] =\> \$$name"
done >&2 <"$TEMPFILE"
rm -f "$TEMPFILE"
我使用了一个临时文件,因为我进行了两次传递(我这样做是出于调试目的)但是如果你不需要第二次传递,那就去做
#!/bin/sh
while read name value
do
eval echo "$name==\$$name"
if
[ -z "`eval echo \\\$$name`" ]
then
echo "$name=\"$value\""
eval "$name=\"$value\""
fi
done <<EOF
A default value for variable A
B default value for variable B
C default value for variable C
PATH /bin:/usr/bin
HOME $HOME
EOF
所以,最后,没有痕迹,你会得到这样的东西:
#!/bin/sh
while read name value
do
if [ -z "`eval echo \\\$$name`" ]
then
eval "$name=\"$value\""
fi
done <<EOF
A default value for variable A
B default value for variable B
C default value for variable C
PATH /bin:/usr/bin
HOME $HOME
ANOTHER_VARIABLE default value for ANOTHER_VARIABLE.
EOF
我已经针对GNU Bash和FreeBSD Bourne Shell对此进行了测试。黄金测试应该是针对AT&amp; T V7 bourne shell进行测试,但是我没有手头进行测试。我为此道歉(但正在努力!):)