例如,我得到了一个bash脚本
[root@test ~]# cat 1.sh
#!/bin/bash
var1=""
var2=""
touch "$var1"
touch $var2
它输出为:
[root@test ~]# bash -x 1.sh
+ var1=
+ var2=
+ touch ''
touch: cannot touch ‘’: No such file or directory
+ touch
touch: missing file operand
所以如果我使用"$var"
over 命令,当它为空时,它会变得''
并破坏我的命令
而如果我使用没有双引号的$var
,它可以工作,但 shell 检查保持投诉到双引号以防止单词拆分
我该如何解决这个问题?
-------------编辑-------
这里touch
是示例,请不要介意这里的命令,目标是让它不输出任何东西
例如
my_command $var1 $var2 $var3 $var4
这些 var 可以是空的,所以如果我双引号它
my_command "$var1" "$var2" "$var3" "$var4"
假设 var1 和 2 为空,那么它将运行为
var1=""
var2=""
var3="some"
var4="thing"
my_command "$var1" "$var2" "$var3" "$var4"
它输出为
my_command '' '' some thing
,并因争论''
而破裂。
如果我这样做
var1=""
var2=""
var3="some"
var4="thing"
my_command $var1 $var2 $var3 $var4
它就像my_command some thing
一样有效,但外壳检查保持投诉:(
您可以从参数列表中省略空变量,如下所示:
my_command ${var1:+"$var1"} ${var2:+"$var2"} ${var3:+"$var3"} ${var4:+"$var4"}
说明:如果var
已定义且为非空,则${var:+something}
将扩展到something
。因此,如果变量不为空,${var:+"$var"}
将扩展到对$var
的正确双引号引用。如果它是空的或未定义的,整个事情就会扩展到零,并且由于外部引用没有双引号,因此它被单词拆分消除。
当不加引号时,空字符串var=""; touch $var
扩展为空(就好像你没有添加它一样)。
但是当var=""; touch "$var"
引用时,它会从var
扩展到空字符串,这是一个无效的文件名参数touch
。
该如何解决这个问题?
没有什么可以解决的,因为它按预期工作。呈现的命令touch "$var"
按预期工作。当var
为空时,将一个空参数传递给touch
命令。
由于创建具有空名称的文件是无效的,因此很高兴touch
通过消息抱怨。
目标是使其不输出任何内容
然后在运行之前检查要touch
的参数是否为非空。
if [ -n "$var" ]; then
somecommand "$var"
fi
如果要从列表中省略参数(如果参数为空),请使用 bash 数组累积现有参数并将它们正确引用传递给命令:
args=()
if [[ -n "$var1" ]]; then
args+=("$var1")
fi
if [[ -n "$var2" ]]; then
args+=("$var2")
fi
somecommand "${args[@]}"
与 bash 数组兼容的 POSIX 替代方案是使用set -- "$@" "$var"
正参数来累积参数或str+="$(printf " %q" "$var")
正确引用的字符串进行eval
。
如果你想从字面上"让它不输出任何内容",那么静默stdout
命令并stderr
命令,通常通过重定向到/dev/null
:
{ somecommand ...; } >/dev/null 2>&1
在尝试使用变量之前,您应该检查变量的有效性。例如,您可以使用if [[ -z $VAR ]]
:
if [[ -z $var1 || -z $var2 || -z $var3 || -z $var4 ]]; then
echo "Error: argument cannot be empty"
exit 1
fi
my_command "$var1" "$var2" "$var3" "$var4"
例如,您还可以将其拆分为不同的if
,以防您想要每个消息的不同消息。