在 Shell 语言中,经常会看到中括号和括号组成的特殊标识,例如:[][[]](())$(())()。这些符号经常使我们非常迷惑,弄清楚它们之间的作用和区别非常必要。

在开始之前,我们先来学习一个 test 命令。

test命令

test 命令主要是用来做表达式的判断,其语法结构如下:

1
test {EXPRESSION}

例如:

1
2
3
4
if test "a" == "a"
then
echo match!
fi

[]

其实 [] 符号的作用与 test 命令一样,都用于判断表达式的真假。只不过 [] 将表达式括起来了,更加易读。上面的例子用 [] 重写就会变成这样:

1
2
3
4
if [ "a" == "a" ]
then
echo match!
fi

让我们来看一个更加复杂点的例子:

1
2
3
4
5
a=12
if [ $a -gt 10 -a $a -lt 15 ]
then
echo match!
fi

[[]]

[[]] 符号与 [] 符号的区别是,在 [[]] 符号里,我们引用变量时可以不再用 $ 符号了,而且还可以使用 && 和 || 运算符。

像上面判断变量 a 的范围,我们在 [] 符号中,只能使用 -gt-a-lt等操作符。但如果用[[]]实现,我们就可以用上&&||操作符:

1
2
3
4
5
a=12
if [[ a -gt 10 && a -lt 15 ]]
then
echo match!
fi

但你会发现我们做算术比较还需要写-lt-gt之类的东西,非常恶心。那么我们可以用下面这个符号。

let 命令

我们在进行算术运算时,我们可以使用 let 命令进行运算:

1
2
3
a=10
let b=a+10
echo $b

在 let 命令中的变量,不需要使用 $ 符号就可以使用。像上面的 a 变量,其实一个变量,但是在第 2 行的 let 语句不需要使用 $ 符号也能成功运算。

(())

这组符号的作用与 let 命令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let命令要好许多。

在这个符号里,我们可以进行整数运算,它的作用和 let 命令一样。

1
2
3
a=10
(( b = a + 10 ))
echo $b

或者我们可以将计算结果作为表达式,如果结果是 0 表示假,其余全部是真。

1
2
3 大专栏  Shell 快速入门(十八):特殊符号的使用
4
5
a=10
if (( a + 10 ))
then
echo true
fi

又或者是:

1
2
3
4
5
a=10
if (( a <= 12 && a > 0))
then
echo great than 10
fi

$(())

这玩意和上面的差不多,但是不会像命令一样有返回值,而是会像变量一样把运算结果替换出来。例如:

1
2
3
a=10
b=$(( a <= 12 && a > 0))
echo $b

输出:1

1
2
3
a=10
b=$(( a <= 12 && a < 0))
echo $b

输出:0

因此如果要让它作为一个表达式的话,就要结合 [] 符号。例如:

1
2
3
4
5
a=10
if [ $(( a <= 12 && a > 0)) -eq 1 ]
then
echo great than 10
fi

对于 (()) 符号而言只有 bash 这个 Shell 有,而 $(()) 则是所有 Shell 都有,更为通用。

()

() 符号表示括号中作为一个子 Shell 运行,运行结果不干扰外层的 Shell。

看看下面这个例子:

1
2
3
a=2
(a=1)
echo $a

输出是:2

因为括号括起来是一个子 Shell,不影响外层 Shell 的运行,所以对 a 赋值为 1 不影响外层结果,外层的 a 变量还是 2。

利用上面子 Shell 这个特性,我们在写 Shell 脚本的时候可以做到不切换当前目录而在其他目录干点事儿。例如:

1
(cd hello; echo "Hello Shell" > hello.txt); pwd; cat hello/hello.txt

上面我进入了子目录 hello,并创建了一个 hello.txt 文档。输出结果是:

1
2
/Users/yurongchan/Yosemite/shell-practice/practice
Hello Shell

可以看到我当前目录没有改变,但是文档已经创建成功了。

{ } 大括号 (Block of code)

这种用法与上面介绍的命令群组非常相似,但有个不同点,它在当前的 shell 执行,不会产生 subshell。 单纯只使用大括号时,作用就像是个没有指定名称的函数一般。

1
2
3
a=2
{ a=1; }
echo $a

上面输出:1

这个用法和 () 用法的区别有两个:

  • 大括号 {} 里的运算是在当前 Shell 运行,会影响外层结果,而括号 ()的不会。
  • 大括号里最后一个语句必须要用 ; 分号结束,否则出错,而括号 () 的并没有这个要求。

Shell 快速入门(十八):特殊符号的使用的更多相关文章

  1. Linux Bash Shell 快速入门

    BASH 的基本语法 最简单的例子 —— Hello World! 关于输入.输出和错误输出 BASH 中对变量的规定(与 C 语言的异同) BASH 中的基本流程控制语法 函数的使用 2.1     ...

  2. Linux Bash Shell快速入门 (三)

    forfor 循环结构与 C 语言中有所不同,在 BASH 中 for 循环的基本结构是: for $var in dostatmentsdone 其中 $var 是循环控制变量, 是 $var 需要 ...

  3. shell 快速入门

    1: 脚本开始行 #!/bin/bash 这一行表明,不管用户选择的是那种交互式shell,该脚本需要使用bash shell来运行. 由于每种shell的语法大不相同,所以这句非常重要. 2:变量 ...

  4. Shell的常用十八条命令

    Shell的18条常用命令整理 1. ls: 类似于dos下的dir命令 ls最常用的参数有三个: -a -l -F. ls –a Linux上的文件以.开头的文件被系统视为隐藏文件,仅用ls命令是看 ...

  5. shell快速入门

    $? 表示上一个命令退出的状态,0表示执行正常,不等于0表示执行不正常. $$ 表示当前进程编号 $ 表示当前脚本名称 $# 表示参数的个数,常用于循环 $*和$@ 都表示参数列表 $n 表示n位置的 ...

  6. Linux Bash Shell快速入门 (二)

    BASH 中的变量介绍BASH 中的变量都是不能含有保留字,不能含有 "-" 等保留字符,也不能含有空格. 简单变量在 BASH 中变量定义是不需要的,没有 "int i ...

  7. Linux Bash Shell快速入门(一)

    BASH 的基本语法· 最简单的例子 —— Hello World! · 关于输入.输出和错误输出 · BASH 中对变量的规定(与 C 语言的异同) · BASH 中的基本流程控制语法 · 函数的使 ...

  8. [译]Kinect for Windows SDK开发入门(十八):Kinect Interaction交互控件

    本文译自 http://dotneteers.net/blogs/vbandi/archive/2013/03/25/kinect-interactions-with-wpf-part-i-getti ...

  9. 1.shell快速入门

    shell是什么?shell是一个命令行解释器,它提供了一个像linux内核发送请求以便运行程序的界面系统程序,用户可以用shell来启动.挂起.停止甚至是编写一些程序.说白了,shell就是用来和内 ...

随机推荐

  1. Redis的数据结构和对象。

    一.简单动态字符串(simple dynamic string--SDS) Redis使用SDS表示字符串值,键值对都用SDS实现.SDS中的字符数组buf以空字符串结尾,好处是可以直接重用一部分C字 ...

  2. IOS下的safari不支持localStorage?

    同事在统计日志的时候,想用localStorag去记载一些什么,但是在各大浏览器都运行的良好的基础上,唯独IOS下的safari一直静静无声,没有任何反应.打印localStorage都是Object ...

  3. h5-钟表动画案例

    1.html代码 <div class="clock"> <div class="line line1"> <div class= ...

  4. sourceTree 代码回滚(git 和http)

    近些时候,有遇到提交后代码有误的情况,所以需要回退到前一个版本.因为不常见,所以每次都不是很熟练,记录于此,以备查阅. 一.[将master重置到这次提交] 在sourceTree中选中错误的提交的下 ...

  5. 吴裕雄--天生自然 PHP开发学习:面向对象

    <?php class Site { /* 成员变量 */ var $url; var $title; /* 成员函数 */ function setUrl($par){ $this->u ...

  6. MyBatis从入门到精通(第9章):Spring集成MyBatis(中)

    MyBatis从入门到精通(第9章):Spring集成MyBatis(中) 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法.应该将应用自身的设计和具体 ...

  7. Servlet&JSP复习笔记 03

    1.Servlet的声明周期 容器如何创建Servlet对象,如何为Servlet对象分配资源,如何调用Servlet对象的方法来处理请求,以及如何销毁Servlet对象的过程. a.实例化 容器调用 ...

  8. linux 查看链接库的版本

    我们编译可执行文件的时候,会链接各种依赖库, 但是怎么知道依赖库的版本正确呢? 下面有几种办法: ldd 这是比较差的,因为打印结果更与位置相关 dpkg -l | grep libprotobuf ...

  9. Oauth2.0详解及安全使用

    引言:刚刚参加工作的时候接到的第一个任务就是接入新浪的联合登录功能,当时新浪用的还是oauth1.0协议.接入的时候没有对oauth协议有过多的了解,只是按照开放平台的接入流程进行开发,当时还在想这么 ...

  10. nginx 配合jersey+netty的奇怪问题

    角色 client proxy nginx server jersey+netty 问题表现 client 直接请求server 正常,返回准确json数据 jsondat client->ng ...