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

All*_*sey 160 syntax bash shell if-statement

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

#!/bin/bash
# With the -n option
if [ -n "$var" ]; then
  # Do something when var is non-zero length
fi
Run Code Online (Sandbox Code Playgroud)

但是-n选项并不是真正需要的:

# Without the -n option
if [ "$var" ]; then
  # Do something when var is non-zero length
fi
Run Code Online (Sandbox Code Playgroud)

哪种方式更好?

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

if [ -z "$var" ]; then
  # Do something when var is zero-length
fi
Run Code Online (Sandbox Code Playgroud)

要么

if [ ! "$var" ]; then
  # Do something when var is zero-length
fi
Run Code Online (Sandbox Code Playgroud)

Pau*_*ce. 367

编辑:这是一个更完整的版本,显示[(aka test)和[[.之间的更多差异.

下表显示是否引用变量,是使用单括号还是双括号以及变量是否仅包含空格是影响使用或不使用测试-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
Run Code Online (Sandbox Code Playgroud)

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

  • 在单括号中引用变量(第2a列)
  • -n在单括号中使用和引用变量(第4a列)
  • 使用带或不带引号的双括号和有或没有-n(第1b - 4b列)

请注意,在第1a列中,从标有"two"的行开始,结果表明[正在评估变量的内容,就好像它们是条件表达式的一部分一样(结果与"T"或"F"中隐含的断言相匹配)描述栏).何时[[使用(第1b列),变量内容被视为字符串而不进行评估.

列3a和5a中的错误是由变量值包括空格而变量未加引号的事实引起的.同样,如列3b和5b所示,[[将变量的内容作为字符串进行计算.

如果您正在使用if ! [[ -n $var ]],那么确保您没有获得意外结果的关键是引用该变量.使用[,没关系.

被抑制的错误消息是"一元运算符预期"或"二元运算符预期".

这是生成上表的脚本.

#!/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
Run Code Online (Sandbox Code Playgroud)

  • 因此,您的`[“`与`[-n”`(OP的第一个问题)的图表表明它们是完全等效的,对吗? (2认同)

cod*_*ter 15

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

通常情况

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
Run Code Online (Sandbox Code Playgroud)

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

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

罕见的情况

在极少数情况下,我们必须区分"被设置为空字符串"与"未被设置",我们可以使用这些:

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
Run Code Online (Sandbox Code Playgroud)

我们也可以使用[[ $var ]]测试:

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
Run Code Online (Sandbox Code Playgroud)

相关文章和文档

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


小智 8

这是一些更多的测试

如果string不为空,则为true:

[ -n "$var" ]
[[ -n $var ]]
test -n "$var"
[ "$var" ]
[[ $var ]]
(( ${#var} ))
let ${#var}
test "$var"
Run Code Online (Sandbox Code Playgroud)

如果string为空,则为true:

[ -z "$var" ]
[[ -z $var ]]
test -z "$var"
! [ "$var" ]
! [[ $var ]]
! (( ${#var} ))
! let ${#var}
! test "$var"
Run Code Online (Sandbox Code Playgroud)


gho*_*g74 -6

用于case/esac测试:

case "$var" in
  "") echo "zero length";;
esac
Run Code Online (Sandbox Code Playgroud)

  • 不谢谢。这不是“案例”的含义。 (17认同)
  • 当有两个以上的选择时,“case”效果最好。 (2认同)