为了账号安全,请及时绑定邮箱和手机立即绑定

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

/ 猿问

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

陪伴而非守候 2019-08-23 15:54:49

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

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

#!/bin/bash# With the -n optionif [ -n "$var" ]; then
  # Do something when var is non-zero lengthfi

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

# Without the -n optionif [ "$var" ]; then
  # Do something when var is non-zero lengthfi

哪种方式更好?

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

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

要么

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


查看完整描述

3 回答

?
天涯尽头无女友

这是一个更完整的版本,显示[(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

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


在单括号中引用变量(第2a列)

-n在单括号中使用和引用变量(第4a列)

使用带或不带引号的双括号和有或没有-n(第1b - 4b列)

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


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


相应地,对于零长度字符串的测试,列6a,5b和6b显示了正确的方法。还要注意,如果否定显示比使用相反操作更清晰的意图,则可以否定这些测试中的任何一个。例如: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


查看完整回答
反对 回复 2019-08-23
?
拉丁的传说

就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

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


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


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


罕见的情况

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


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

我们也可以使用-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


查看完整回答
反对 回复 2019-08-23
?
手掌心

正确答案如下:

if [[ -n $var ]] ; then
  blahfi

注意使用[[...]],正确处理为您引用变量。


查看完整回答
反对 回复 2019-08-23

添加回答

回复

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信