string 如何判断字符串是否未在 Bash shell 脚本中定义
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/228544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to tell if a string is not defined in a Bash shell script
提问by Setjmp
If I want to check for the null string I would do
如果我想检查空字符串,我会做
[ -z $mystr ]
but what if I want to check whether the variable has been defined at all? Or is there no distinction in Bash scripting?
但是如果我想检查变量是否已经定义了怎么办?或者在 Bash 脚本中没有区别?
采纳答案by Jonathan Leffler
I think the answer you are after is implied (if not stated) by Vinko's answer, though it is not spelled out simply. To distinguish whether VAR is set but empty or not set, you can use:
我认为Vinko的回答暗示了您所寻求的答案(如果没有说明),尽管它没有简单地说明。要区分 VAR 是否设置但为空或未设置,您可以使用:
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "$VAR" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
You probably can combine the two tests on the second line into one with:
您可能可以将第二行的两个测试合并为一个:
if [ -z "$VAR" -a "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
However, if you read the documentation for Autoconf, you'll find that they do not recommend combining terms with '-a
' and do recommend using separate simple tests combined with &&
. I've not encountered a system where there is a problem; that doesn't mean they didn't used to exist (but they are probably extremely rare these days, even if they weren't as rare in the distant past).
但是,如果您阅读 Autoconf 的文档,您会发现他们不建议将术语与 ' -a
'结合使用,而是建议使用单独的简单测试与&&
. 我没有遇到过有问题的系统;这并不意味着它们曾经不存在(但它们现在可能非常罕见,即使它们在遥远的过去并不罕见)。
You can find the details of these, and other related shell parameter expansions, the test
or [
command and conditional expressionsin the Bash manual.
您可以在 Bash 手册中找到这些细节以及其他相关的shell 参数扩展、test
or[
命令和条件表达式。
I was recently asked by email about this answer with the question:
我最近通过电子邮件向我询问了这个问题的答案:
You use two tests, and I understand the second one well, but not the first one. More precisely I don't understand the need for variable expansion
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
Wouldn't this accomplish the same?
if [ -z "${VAR}" ]; then echo VAR is not set at all; fi
你用了两个测试,我理解第二个,但不是第一个。更准确地说,我不明白变量扩展的必要性
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
这不会达到同样的效果吗?
if [ -z "${VAR}" ]; then echo VAR is not set at all; fi
Fair question - the answer is 'No, your simpler alternative does not do the same thing'.
公平的问题 - 答案是“不,您的更简单的选择不会做同样的事情”。
Suppose I write this before your test:
假设我在你的测试之前写了这个:
VAR=
Your test will say "VAR is not set at all", but mine will say (by implication because it echoes nothing) "VAR is set but its value might be empty". Try this script:
您的测试会说“根本没有设置 VAR”,但我的会说(暗示,因为它没有回显)“设置了 VAR,但它的值可能为空”。试试这个脚本:
(
unset VAR
if [ -z "${VAR+xxx}" ]; then echo JL:1 VAR is not set at all; fi
if [ -z "${VAR}" ]; then echo MP:1 VAR is not set at all; fi
VAR=
if [ -z "${VAR+xxx}" ]; then echo JL:2 VAR is not set at all; fi
if [ -z "${VAR}" ]; then echo MP:2 VAR is not set at all; fi
)
The output is:
输出是:
JL:1 VAR is not set at all
MP:1 VAR is not set at all
MP:2 VAR is not set at all
In the second pair of tests, the variable is set, but it is set to the empty value. This is the distinction that the ${VAR=value}
and ${VAR:=value}
notations make. Ditto for ${VAR-value}
and ${VAR:-value}
, and ${VAR+value}
and ${VAR:+value}
, and so on.
在第二对测试中,变量被设置,但它被设置为空值。这是${VAR=value}
和${VAR:=value}
符号的区别。同上,用于${VAR-value}
和${VAR:-value}
,和${VAR+value}
和${VAR:+value}
,等等。
As Gilipoints out in his answer, if you run bash
with the set -o nounset
option, then the basic answer above fails with unbound variable
. It is easily remedied:
正如Gili在他的回答中指出的那样,如果您bash
使用该set -o nounset
选项运行,那么上面的基本答案会以unbound variable
. 它很容易补救:
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "${VAR-}" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
Or you could cancel the set -o nounset
option with set +u
(set -u
being equivalent to set -o nounset
).
或者您可以set -o nounset
使用set +u
(set -u
相当于set -o nounset
)取消该选项。
回答by Vinko Vrsalovic
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO=""
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO="a"
~> if [ -z $FOO ]; then echo "EMPTY"; fi
~>
-z works for undefined variables too. To distinguish between an undefined and a defined you'd use the things listed hereor, with clearer explanations, here.
-z 也适用于未定义的变量。要区分未定义和已定义,您可以使用此处列出的内容,或者更清晰的解释,此处。
Cleanest way is using expansion like in these examples. To get all your options check the Parameter Expansion section of the manual.
最干净的方法是使用这些示例中的扩展。要获得所有选项,请检查手册的参数扩展部分。
Alternate word:
替代词:
~$ unset FOO
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
~$ FOO=""
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
DEFINED
Default value:
默认值:
~$ FOO=""
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
~$ unset FOO
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
UNDEFINED
Of course you'd use one of these differently, putting the value you want instead of 'default value' and using the expansion directly, if appropriate.
当然,您会以不同的方式使用其中之一,将您想要的值而不是“默认值”放在适当的位置并直接使用扩展。
回答by Vinko Vrsalovic
Advanced bash scripting guide, 10.2. Parameter Substitution:
高级 bash 脚本指南,10.2。参数替换:
- ${var+blahblah}: if var is defined, 'blahblah' is substituted for the expression, else null is substituted
- ${var-blahblah}: if var is defined, it is itself substituted, else 'blahblah' is substituted
- ${var?blahblah}: if var is defined, it is substituted, else the function exists with 'blahblah' as an error message.
- ${var+blahblah}:如果定义了 var,则用 'blahblah' 代替表达式,否则用 null 代替
- ${var-blahblah}:如果定义了 var,它本身被替换,否则 'blahblah' 被替换
- ${var?blahblah}:如果定义了 var,则将其替换,否则该函数存在并带有 'blahblah' 作为错误消息。
to base your program logic on whether the variable $mystr is defined or not, you can do the following:
要将程序逻辑基于变量 $mystr 是否已定义,您可以执行以下操作:
isdefined=0
${mystr+ export isdefined=1}
now, if isdefined=0 then the variable was undefined, if isdefined=1 the variable was defined
现在,如果 isdefined=0 则变量未定义,如果 isdefined=1 变量已定义
This way of checking variables is better than the above answer because it is more elegant, readable, and if your bash shell was configured to error on the use of undefined variables (set -u)
, the script will terminate prematurely.
这种检查变量的方法比上面的答案更好,因为它更优雅、更易读,而且如果你的 bash shell 被配置为在使用未定义变量时出错(set -u)
,脚本将过早终止。
Other useful stuff:
其他有用的东西:
to have a default value of 7 assigned to $mystr if it was undefined, and leave it intact otherwise:
如果 $mystr 未定义,则将默认值 7 分配给它,否则保持不变:
mystr=${mystr- 7}
to print an error message and exit the function if the variable is undefined:
如果变量未定义,则打印错误消息并退出函数:
: ${mystr? not defined}
Beware here that I used ':' so as not to have the contents of $mystr executed as a command in case it is defined.
请注意,我在这里使用了 ':' 以免 $mystr 的内容作为命令执行,以防它被定义。
回答by k107
A summary of tests.
测试总结。
[ -n "$var" ] && echo "var is set and not empty"
[ -z "$var" ] && echo "var is unset or empty"
[ "${var+x}" = "x" ] && echo "var is set" # may or may not be empty
[ -n "${var+x}" ] && echo "var is set" # may or may not be empty
[ -z "${var+x}" ] && echo "var is unset"
[ -z "${var-x}" ] && echo "var is set and empty"
回答by Gili
https://stackoverflow.com/a/9824943/14731contains a better answer (one that is more readable and works with set -o nounset
enabled). It works roughly like this:
https://stackoverflow.com/a/9824943/14731包含一个更好的答案(一个更具可读性并且可以使用的答案set -o nounset
)。它的工作原理大致如下:
if [ -n "${VAR-}" ]; then
echo "VAR is set and is not empty"
elif [ "${VAR+DEFINED_BUT_EMPTY}" = "DEFINED_BUT_EMPTY" ]; then
echo "VAR is set, but empty"
else
echo "VAR is not set"
fi
回答by Felix Leipold
The explicit way to check for a variable being defined would be:
检查正在定义的变量的显式方法是:
[ -v mystr ]
回答by Aaron Davies
another option: the "list array indices" expansion:
另一种选择:“列表数组索引”扩展:
$ unset foo
$ foo=
$ echo ${!foo[*]}
0
$ foo=bar
$ echo ${!foo[*]}
0
$ foo=(bar baz)
$ echo ${!foo[*]}
0 1
the only time this expands to the empty string is when foo
is unset, so you can check it with the string conditional:
唯一一次扩展为空字符串是 whenfoo
未设置,因此您可以使用字符串条件检查它:
$ unset foo
$ [[ ${!foo[*]} ]]; echo $?
1
$ foo=
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=bar
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=(bar baz)
$ [[ ${!foo[*]} ]]; echo $?
0
should be available in any bash version >= 3.0
应该在任何 bash 版本 >= 3.0 中可用
回答by Sacrilicious
not to shed this bike even further, but wanted to add
不要进一步摆脱这辆自行车,而是想添加
shopt -s -o nounset
is something you could add to the top of a script, which will error if variables aren't declaredanywhere in the script. The message you'd see is unbound variable
, but as others mention it won't catch an empty string or null value. To make sure any individual value isn't empty, we can test a variable as it's expanded with ${mystr:?}
, also known as dollar sign expansion, which would error with parameter null or not set
.
是您可以添加到脚本顶部的内容,如果未在脚本中的任何位置声明变量,则会出错。您看到的消息是unbound variable
,但正如其他人提到的那样,它不会捕获空字符串或空值。为了确保任何单个值不为空,我们可以测试一个变量,因为它用 扩展${mystr:?}
,也称为美元符号扩展,它会出错parameter null or not set
。
回答by funroll
The Bash Reference Manualis an authoritative source of information about bash.
的击参考手册是约bash的信息的权威来源。
Here's an example of testing a variable to see if it exists:
这是测试变量以查看它是否存在的示例:
if [ -z "$PS1" ]; then
echo This shell is not interactive
else
echo This shell is interactive
fi
(From section 6.3.2.)
(来自第 6.3.2 节。)
Note that the whitespace after the open [
and before the ]
is not optional.
需要注意的是后开的空白[
和以前]
是不可选的。
Tips for Vim users
给 Vim 用户的提示
I had a script that had several declarations as follows:
我有一个脚本有几个声明如下:
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
But I wanted them to defer to any existing values. So I re-wrote them to look like this:
但我希望他们遵循任何现有的价值观。所以我把它们改写成这样:
if [ -z "$VARIABLE_NAME" ]; then
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
fi
I was able to automate this in vim using a quick regex:
我能够使用快速正则表达式在 vim 中自动执行此操作:
s/\vexport ([A-Z_]+)\=("[^"]+")\n/if [ -z "$" ]; then\r export =\rfi\r/gc
This can be applied by selecting the relevant lines visually, then typing :
. The command bar pre-populates with :'<,'>
. Paste the above command and hit enter.
这可以通过视觉选择相关行,然后键入:
. 命令栏预填充:'<,'>
. 粘贴上面的命令并按回车键。
Tested on this version of Vim:
在这个版本的 Vim 上测试:
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 22 2015 15:38:58)
Compiled by [email protected]
Windows users may want different line endings.
Windows 用户可能需要不同的行尾。
回答by nfleury
A shorter version to test undefined variable can simply be:
测试未定义变量的较短版本可以简单地是:
test -z ${mystr} && echo "mystr is not defined"