如何在命令行中仅在变量已设置的情况下对shell变量使用双引号?

rjjhvcjd  于 2023-10-23  发布在  Shell
关注(0)|答案(2)|浏览(122)

我需要执行一个bash命令,只有当变量被设置时,我才想在命令行中包含该变量。诀窍是变量中可以有一个空格,并且变量必须作为单个参数传递。
下面的命令在foo未被设置的情况下不会执行正确的操作(但是如果设置了它的话),它将向命令栏传递一个空参数,因为$FOO没有被设置,而是被双引号括起来。

FOO=""
bar "$FOO"

下面的命令修复了$FOO未设置的缺陷,但添加了如果$FOO中有空格则传递两个参数的缺陷。

FOO="one two"
bar $FOO

我尝试使用bar ${FOO+"}$FOO${FOO+"},但尽管它在那里使用了引号,但它仍然传递了两个参数。我想,如果使用eval时引用所有其他参数(这里没有列出),如果没有大量的测试,这些参数是不可能正确的,那么这个问题也可以解决。
显然,你可以说if [ "$Z" ]; then bar "$Z"; else bar; fi,但这并不能扩展。
实现这一点的最佳方式是什么?

pkwftd7m

pkwftd7m1#

使用${var:+"$var"}
这是因为替代值尊重引号:

unset var
set -- ${var:+"$var"}
echo "Unset: $# args"

var=""
set -- ${var:+"$var"}
echo "Blank: $# args"

var="foo bar"
set -- ${var:+"$var"}
echo "Multiple words: $# args"

输出

Unset: 0 args
Blank: 0 args
Multiple words: 1 args

(To传递空字符串,但不传递未设置的值,使用${var+"$var"},不带冒号)

4urapxun

4urapxun2#

魔术壳数组引用语法是我能想到的最好的答案,因为在一般情况下,没有人知道有多少元素存在,他们可能仍然需要双引号。
对于简单的程序,您可能有像bar "$@"这样的东西,它将对shell的所有参数进行双引号。这对我的用例来说不是很方便,因为我必须跳转到一个函数中,并失去对真实的命令参数的访问。
因此,对于这个用例,请使用临时shell数组:

Z=("one two")
bar "${Z[@]}"

你可以看到这在行动与:

for Z in "foo bar" ""; do
 echo "Running case with Z=<$Z>"
 if [ "$Z" ]; then Z=("$Z"); else Z=(); fi
 for f in 1 "${Z[@]}" 2; do echo $f; done
done

这将产生(期望的/正确的)输出:

Running case with Z=<foo bar>
1
foo bar
2
Running case with Z=<>
1
2

(错误的输出将在单独的行上显示foo和bar,或者在1和2之间显示空行)。

相关问题