[[ ]]是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立。

test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好;test 做不到的,[[ ]] 还能做到。可以认为 [[ ]] 是 test 的升级版,对细节进行了优化,并且扩展了一些功能。

[[ ]] 的用法为:

[[ expression ]]

当 [[ ]] 判断 expression 成立时,退出状态为 0,否则为非 0 值。注意[[ ]]expression之间的空格,这两个空格是必须的,否则会导致语法错误。

[[ ]] 不需要注意某些细枝末节

[[ ]] 是 Shell 内置关键字,不是命令,在使用时没有给函数传递参数的过程,所以 test 命令的某些注意事项在 [[ ]] 中就不存在了,具体包括:

  • 不需要把变量名用双引号""包围起来,即使变量是空值,也不会出错。
  • 不需要、也不能对 >、< 进行转义,转义后会出错。

请看下面的演示代码:

#!/bin/bash

read str1
read str2 if [[ -z $str1 ]] || [[ -z $str2 ]] #不需要对变量名加双引号
then
echo "字符串不能为空"
elif [[ $str1 < $str2 ]] #不需要也不能对 < 进行转义
then
echo "str1 < str2"
else
echo "str1 >= str2"
fi

运行结果:
http://c.biancheng.net/shell/
http://data.biancheng.net/
str1 < str2

[[ ]] 支持逻辑运算符

对多个表达式进行逻辑运算时,可以使用逻辑运算符将多个 test 命令连接起来,例如:

[ -z "$str1" ] || [ -z "$str2" ]

你也可以借助选项把多个表达式写在一个 test 命令中,例如:

[ -z "$str1" -o -z "$str2" ]

但是,这两种写法都有点“别扭”,完美的写法是在一个命令中使用逻辑运算符将多个表达式连接起来。我们的这个愿望在 [[ ]] 中实现了,[[ ]]  支持 &&、|| 和 ! 三种逻辑运算符。

使用 [[ ]] 对上面的语句进行改进:

[[ -z $str1 || -z $str2 ]]

这种写法就比较简洁漂亮了。

注意,[[ ]] 剔除了 test 命令的-o-a选项,你只能使用 || 和 &&。这意味着,你不能写成下面的形式:

[[ -z $str1 -o -z $str2 ]]

当然,使用逻辑运算符将多个 [[ ]] 连接起来依然是可以的,因为这是 Shell 本身提供的功能,跟 [[ ]] 或者 test 没有关系,如下所示:

[[ -z $str1 ]] || [[ -z $str2 ]]

该表总结了各种写法的对错
test 或 [] [[ ]]
[ -z "$str1" ] || [ -z "$str2" ] [[ -z $str1 ]] || [[ -z $str2 ]]
[ -z "$str1" -o -z "$str2" ] [[ -z $str1 -o -z $str2 ]] ×
[[ -z $str1 || -z $str2 ]] × [[ -z $str1 || -z $str2 ]]

[[ ]] 支持正则表达式

在 Shell [[ ]] 中,可以使用=~来检测字符串是否符合某个正则表达式,它的用法为:

[[ str =~ regex ]]

str 表示字符串,regex 表示正则表达式。

下面的代码检测一个字符串是否是手机号:

  1. #!/bin/bash
  2. read tel
  3. if [[ $tel =~ ^1[0-9]{10}$ ]]
  4. then
  5. echo "你输入的是手机号码"
  6. else
  7. echo "你输入的不是手机号码"
  8. fi

运行结果1:
13203451100
你输入的是手机号码

运行结果2:
132034511009
你输入的不是手机号码

^1[0-9]{10}$的说明:

  • ^匹配字符串的开头(一个位置);
  • [0-9]{10}匹配连续的十个数字;
  • $匹配字符串的末尾(一个位置)。

本文并不打算讲解正则表达式的语法,不了解的读者请猛击《正则表达式30分钟入门教程》。

总结

有了 [[ ]],你还有什么理由使用 test 或者 [ ],[[ ]] 完全可以替代之,而且更加方便,更加强大。

但是 [[ ]] 对数字的比较仍然不友好,所以我建议,以后大家使用 if 判断条件时,用 (()) 来处理整型数字,用 [[ ]] 来处理字符串或者文件。

Shell [[]]详解:检测某个条件是否成立的更多相关文章

  1. .NET DLL 保护措施详解(五)常规条件下的破解

    为了证实在常规手段破解下能有效保护程序核心功能(演示版本对AES加解密算法及数据库的密钥(一段字符串)进行了保护),特对此DLL保护思路进行相应的测试,包含了反编译及反射测试,看是否能得到AES加解密 ...

  2. Linux的Bash Shell详解

    一.Bash Shell概述 1.什么是bash         bash是Bourne Again Shell的简称,是从unix系统中的sh发展而来的,是用户和Linux内核交互的工具,用户通过b ...

  3. hadoop shell 详解

    概述  所有的hadoop命令均由bin/hadoop脚本引发.不指定参数运行hadoop脚本会打印所有命令的描述.  用法: hadoop [--config confdir] [COMMAND] ...

  4. SHELL 详解

    http://blog.csdn.net/vah101/article/details/6173488 ( a=2;b=4;c=9; ) 子shell 环境 { a=2;b=4;c=9; } 当前sh ...

  5. 每篇半小时1天入门MongoDB——3.MongoDB可视化及shell详解

    本篇主要介绍MongoDB可视化操作以及shell使用及命令,备份恢复.数据导入导出. MongoVUE安装和简单使用 使用mongo.exe 管理数据库虽然可行,功能也挺强大,但每次都要敲命令,即繁 ...

  6. Linux之shell详解

    Shell是什么 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个界 ...

  7. Impala shell详解

    不多说,直接上干货! 查看帮助文档 impala-shell -h 刷新整个云数据 impala-shell -ruse impala;show tables; 去格式化,查询大数据量时可以提高性能 ...

  8. Shell—详解$0、$1、$2、$#、$*、$@、$?、$$变量

    预定义变量:常用来获取命令行的输入 变量 作用 $0 当前Shell脚本本身的文件名称 $1 脚本接收的第一个参数($1-$9:第1-9个命令行参数名) $2 脚本接收的第二个参数($1-$9:第1- ...

  9. Shell—详解$( )、$(( ))、``与${ }的区别

    https://www.jianshu.com/p/2237f029c385 https://www.cnblogs.com/chenpython123/p/11052276.html https:/ ...

随机推荐

  1. maven环境变量配置及测试

    首先要确认,你是否已经安装了jdk,并且已经成功配置了环境变量. 和java配置类似,计算机右键属性->高级系统设置->环境变量. 添加如下变量: 变量名:maven_home 变量值:C ...

  2. tac - 反转显示文件

    总览 (SYNOPSIS) ../src/tac [OPTION]... [FILE]... 描述 (DESCRIPTION) 把 每个 文件 FILE 显示在 标准输出, 后面 的 行 放在 前面. ...

  3. C基础学习记录

    函数 1:子函数定义的变量只在调用的时候才会分配空间,调用结束后会收回空间. 2:在调用子函数时只会向函数传递值,是单向传递的. 3.返回值的类型一般与函数的类型一致,如果不一致会以函数类型为准. 4 ...

  4. show line numbers

  5. 八、结构模式之组合(Composite)模式

    组合模式属于对象的结构模式,有时又叫做部分-整体模式,组合模式将对象组织到树结构中,可以用来描述整体与部分的联系.其可以使客户端将单纯元素和组合元素同等对待. 当需求中是体现部分与整体层次的结构时,以 ...

  6. centos7 nodejs二进制安装

    1.安装文件下载 1.下载地址:http://nodejs.cn/download/ 2.选择一个合适的版本下载 2.安装步骤 1.将安装包上传到指定位置(我习惯放到:/usr/local/appli ...

  7. 「AHOI / HNOI2018」转盘 解题报告

    「AHOI / HNOI2018」转盘 可能是我语文水平不太行... 首先可以猜到一些事实,这个策略一定可以被一个式子表示出来,不然带修修改个锤子. 然后我们发现,可以枚举起点,然后直接往前走,如果要 ...

  8. targetSdkVersion和与target属性的区别

    参考:http://blog.csdn.net/dai_zhenliang/article/details/8175781 AndroidMenifest.xml中targetSdkVersion和p ...

  9. 如何禁止C++默认成员函数

    如何禁止C++默认成员函数 发表于 2016-03-02   |   分类于 C++  |   阅读次数 17 前言 前几天在一次笔试过程中被问到C++如何设计禁止调用默认构造函数,当时简单的想法是直 ...

  10. 一个小BUG引发的思考。(论开发与测试之间的那点事)

    标题不是“一个馒头引发的血案”. 言归正传:今天上午测试的时候,发现了一个BUG,如图: 一个用肉眼就能发现的BUG.原因当然是因为开发同事没有自测试,流入到了测试人员这里了. 无非是开发同事不严谨造 ...