在 Bash 中测试非零长度字符串:[ -n "$var" ] 或 [ "$var" ]

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3869072/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:43:38  来源:igfitidea点击:

Test for non-zero length string in Bash: [ -n "$var" ] or [ "$var" ]

bashshellif-statementsyntax

提问by AllenHalsey

I've seen Bash scripts test for a non-zero length string in two different ways. Most scripts use the -noption:

我已经看到 Bash 脚本以两种不同的方式测试非零长度的字符串。大多数脚本使用该-n选项:

#!/bin/bash
# With the -n option
if [ -n "$var" ]; then
  # Do something when var is non-zero length
fi

But the -n option isn't really needed:

但实际上并不需要 -n 选项:

# Without the -n option
if [ "$var" ]; then
  # Do something when var is non-zero length
fi

Which is the better way?

哪种方法更好?

Similarly, which is the better way for testing for zero-length:

同样,这是测试零长度的更好方法:

if [ -z "$var" ]; then
  # Do something when var is zero-length
fi

or

或者

if [ ! "$var" ]; then
  # Do something when var is zero-length
fi

回答by Paused until further notice.

Edit:This is a more complete version that shows more differences between [(aka test) and [[.

编辑:这是一个更完整的版本,显示了[(aka test) 和[[.

The following table shows that whether a variable is quoted or not, whether you use single or double brackets and whether the variable contains only a space are the things that affect whether using a test with or without -n/-zis suitable for checking a variable.

下表显示了变量是否被引用,使用单括号还是双括号以及变量是否只包含空格是影响使用带或不带的测试-n/-z是否适合检查变量的因素。

     | 1a    2a    3a    4a    5a    6a   | 1b    2b    3b    4b    5b    6b
     | [     ["    [-n   [-n"  [-z   [-z" | [[    [["   [[-n  [[-n" [[-z  [[-z"
-----+------------------------------------+------------------------------------
unset| false false true  false true  true | false false false false true  true
null | false false true  false true  true | false false false false true  true
space| false true  true  true  true  false| true  true  true  true  false false
zero | true  true  true  true  false false| true  true  true  true  false false
digit| true  true  true  true  false false| true  true  true  true  false false
char | true  true  true  true  false false| true  true  true  true  false false
hyphn| true  true  true  true  false false| true  true  true  true  false false
two  | -err- true  -err- true  -err- false| true  true  true  true  false false
part | -err- true  -err- true  -err- false| true  true  true  true  false false
Tstr | true  true  -err- true  -err- false| true  true  true  true  false false
Fsym | false true  -err- true  -err- false| true  true  true  true  false false
T=   | true  true  -err- true  -err- false| true  true  true  true  false false
F=   | false true  -err- true  -err- false| true  true  true  true  false false
T!=  | true  true  -err- true  -err- false| true  true  true  true  false false
F!=  | false true  -err- true  -err- false| true  true  true  true  false false
Teq  | true  true  -err- true  -err- false| true  true  true  true  false false
Feq  | false true  -err- true  -err- false| true  true  true  true  false false
Tne  | true  true  -err- true  -err- false| true  true  true  true  false false
Fne  | false true  -err- true  -err- false| true  true  true  true  false false

If you want to know if a variable is non-zero length, do any of the following:

如果您想知道变量是否为非零长度,请执行以下任一操作:

  • quote the variable in single brackets (column 2a)
  • use -nand quote the variable in single brackets (column 4a)
  • use double brackets with or without quoting and with or without -n(columns 1b - 4b)
  • 在单括号中引用变量(第 2a 列)
  • 使用-n并引用单括号中的变量(第 4a 列)
  • 使用带或不带引号的双括号,带或不带-n(第 1b - 4b 列)

Notice in column 1a starting at the row labeled "two" that the result indicates that [is evaluating the contentsof the variable as if they were part of the conditional expression (the result matches the assertion implied by the "T" or "F" in the description column). When [[is used (column 1b), the variable content is seen as a string and not evaluated.

请注意,在第 1a 列中,从标记为“二”的行开始,结果表明[正在评估变量的内容,就好像它们是条件表达式的一部分一样(结果与中的“T”或“F”隐含的断言匹配说明栏)。当[[被使用(柱1b)中,可变内容被看作是一个字符串,不进行评价。

The errors in columns 3a and 5a are caused by the fact that the variable value includes a space and the variable is unquoted. Again, as shown in columns 3b and 5b, [[evaluates the variable's contents as a string.

第 3a 和 5a 列中的错误是由变量值包含空格且变量未加引号引起的。同样,如第 3b 和 5b 列所示,[[将变量的内容计算为字符串。

Correspondingly, for tests for zero-length strings, columns 6a, 5b and 6b show the correct ways to do that. Also note that any of these tests can be negated if negating shows a clearer intent than using the opposite operation. For example: if ! [[ -n $var ]].

相应地,对于零长度字符串的测试,第 6a、5b 和 6b 列显示了正确的方法。另请注意,如果否定比使用相反的操作显示出更清晰的意图,则可以否定这些测试中的任何一个。例如:if ! [[ -n $var ]]

If you're using [, the key to making sure that you don't get unexpected results is quoting the variable. Using [[, it doesn't matter.

如果您使用的是[,确保不会得到意外结果的关键是引用变量。使用[[,没关系。

The error messages, which are being suppressed, are "unary operator expected" or "binary operator expected".

被抑制的错误消息是“期望一元运算符”或“期望二元运算符”。

This is the script that produced the table above.

这是生成上表的脚本。

#!/bin/bash
# by Dennis Williamson
# 2010-10-06, revised 2010-11-10
# for http://stackoverflow.com/q/3869072
# designed to fit an 80 character terminal

dw=5    # description column width
w=6     # table column width

t () { printf '%-*s' "$w" " true"; }
f () { [[ $? == 1 ]] && printf '%-*s' "$w" " false" || printf '%-*s' "$w" " -err-"; }

o=/dev/null

echo '     | 1a    2a    3a    4a    5a    6a   | 1b    2b    3b    4b    5b    6b'
echo '     | [     ["    [-n   [-n"  [-z   [-z" | [[    [["   [[-n  [[-n" [[-z  [[-z"'
echo '-----+------------------------------------+------------------------------------'

while read -r d t
do
    printf '%-*s|' "$dw" "$d"

    case $d in
        unset) unset t  ;;
        space) t=' '    ;;
    esac

    [ $t ]        2>$o  && t || f
    [ "$t" ]            && t || f
    [ -n $t ]     2>$o  && t || f
    [ -n "$t" ]         && t || f
    [ -z $t ]     2>$o  && t || f
    [ -z "$t" ]         && t || f
    echo -n "|"
    [[ $t ]]            && t || f
    [[ "$t" ]]          && t || f
    [[ -n $t ]]         && t || f
    [[ -n "$t" ]]       && t || f
    [[ -z $t ]]         && t || f
    [[ -z "$t" ]]       && t || f
    echo

done <<'EOF'
unset
null
space
zero    0
digit   1
char    c
hyphn   -z
two     a b
part    a -a
Tstr    -n a
Fsym    -h .
T=      1 = 1
F=      1 = 2
T!=     1 != 2
F!=     1 != 1
Teq     1 -eq 1
Feq     1 -eq 2
Tne     1 -ne 2
Fne     1 -ne 1
EOF

回答by codeforester

It is better to use the more powerful[[as far as Bash is concerned.

就 Bash 而言,最好使用更强大的[[

Usual cases

常见情况

if [[ $var ]]; then   # var is set and it is not empty
if [[ ! $var ]]; then # var is not set or it is set to an empty string

The above two constructs look clean and readable. They should suffice in most cases.

以上两个结构看起来干净且可读。在大多数情况下,它们应该足够了。

Note that we don't need to quote the variable expansions inside [[as there is no danger of word splittingand globbing.

请注意,我们不需要引用内部的变量扩展,[[因为没有分globbing 的危险。

To prevent shellcheck's soft complaints about [[ $var ]]and [[ ! $var ]], we could use the -noption.

为了防止shellcheck[[ $var ]]and的软抱怨[[ ! $var ]],我们可以使用该-n选项。

Rare cases

罕见病例

In the rare case of us having to make a distinction between "being set to an empty string" vs "not being set at all", we could use these:

在我们必须区分“被设置为空字符串”与“根本没有被设置”之间的罕见情况下,我们可以使用这些:

if [[ ${var+x} ]]; then           # var is set but it could be empty
if [[ ! ${var+x} ]]; then         # var is not set
if [[ ${var+x} && ! $var ]]; then # var is set and is empty

We can also use the -vtest:

我们也可以使用-v测试:

if [[ -v var ]]; then             # var is set but it could be empty
if [[ ! -v var ]]; then           # var is not set
if [[ -v var && ! $var ]]; then   # var is set and is empty
if [[ -v var && -z $var ]]; then  # var is set and is empty


Related posts and documentation

相关帖子和文档

There are a plenty of posts related to this topic. Here are a few:

有很多与此主题相关的帖子。以下是一些:

回答by Steven Penny

Here are some more tests

这里还有一些测试

True if string is not empty:

如果字符串不为空,则为真:

[ -n "$var" ]
[[ -n $var ]]
test -n "$var"
[ "$var" ]
[[ $var ]]
(( ${#var} ))
let ${#var}
test "$var"

True if string is empty:

如果字符串为空则为真:

[ -z "$var" ]
[[ -z $var ]]
test -z "$var"
! [ "$var" ]
! [[ $var ]]
! (( ${#var} ))
! let ${#var}
! test "$var"

回答by user1310789

An alternative and perhaps more transparent way of evaluating an empty environment variable is to use...

评估空环境变量的另一种可能更透明的方法是使用...

  if [ "x$ENV_VARIABLE" != "x" ] ; then
      echo 'ENV_VARIABLE contains something'
  fi

回答by user2592126

The correct answer is the following:

正确答案如下:

if [[ -n $var ]] ; then
  blah
fi

Note the use of the [[...]], which correctly handles quoting the variables for you.

请注意 的使用[[...]],它可以正确地为您处理引用变量。

回答by ghostdog74

Use case/esacto test:

使用case/esac测试:

case "$var" in
  "") echo "zero length";;
esac