前言:在bash中遇到各种括号,同时在进行字符数值比较判定时,总是不断出现问题,于是通过参考《advanced bash-scripting guide》,同时在centos 6.7版本上进行测试,现况总结如下。如有纰漏,望指正。

一.()

一个命令组合,相当于一个命令组

[root@mghuee~chunlanyy testdir]# I=;(I=xyz;echo $I;);echo $I
xyz

二.{}

同"{}",也为一个命令组合,与"()"的区别就是前者在是当前shell中进行,而后者在里面子shell中进行

[root@mghuee~chunlanyy testdir]# I=;(echo $I;I=xyz;echo $I;);echo $I

xyz

[root@mghuee~chunlanyy testdir]# I=;{ echo $I;I=xyz;echo $I; };echo $I

xyz
xyz

从例子中可以看得,"()"中的赋值只能影响到自身子shell,并不会赋值给父shell,而"{}"则只是在同一shell进行

另外需要注意的是,"{}"是一个keyword,所以在命令与两边的"{"需用空格隔离,同时使用";"表示命令结束。

[root@mghuee~chunlanyy testdir]# type {
{ is a shell keyword

三.[]

"[]"主要用作条件判断,判断对象包括文件类型和赋值比较

[root@mghuee~chunlanyy testdir]# type [
[ is a shell builtin

我们可以看到"["是一个内部命令,基本可认为等同于test命令

[root@mghuee~chunlanyy testdir]# [  -lt  ] && echo yes || echo no
no
[root@mghuee~chunlanyy testdir]# test -lt && echo yes || echo no
no

常见的比较测试如下:

数字测试:-eq -ne -lt -le -gt -ge

文件测试:-r、-l、-w、-x、-f、-d、-s、-nt、-ot

字符串测试:=、!=、-n、-z、\>、\<

逻辑测试:-a、-o、!

数学运算:支持整数运算,但已被"((...))"取代

注意的几点:

1.数字比较只能用-lt这样的比较符,而不能使用"<"这样的比较符,即便是加了转义符的"\<"

[root@mghuee~chunlanyy testdir]# [  >  ] && echo yes || echo no
yes

很显然,"1>2"应该是错误的,但是显示"yes",实际上此处">"并非算术比较中的大于号,而为重定向输出,通过ls命令即可查看出当前目录下多出一个文件名为2的文件

[root@mghuee~chunlanyy testdir]# ll -l
total
-rw-r--r--. root root Jun :

有人也会试想通过转义符进行数值比较

[root@mghuee~chunlanyy testdir]# [  \>  ] && echo yes || echo no
no

通过此比较符合我们的预期,但是"\>"在此并非进行我们日常中理解的大小数值比较

[root@mghuee~chunlanyy testdir]# [ a \>  ] && echo yes || echo no
yes

此处比较是进行ASCII码值大小比较,同时此处只能支持单字符的大小比较

[root@mghuee~chunlanyy testdir]# [  \>  ] && echo yes || echo no
yes

2."[]"支持的逻辑运算符为-a、-o、!,此处-a、-o相当于是test命令的一个参数,不能使用&&、||

[root@mghuee~chunlanyy testdir]# [  -lt   &&  -lt  ] && echo yes || echo no
-bash: [: missing `]'
no

&&和||是强逻辑运算,会对命令进行拆分,在上述举例中已经拆分成"[ 1 -lt  2 " && "1 -lt 3 ]",故会显示没有配对的"["

在逻辑运算时,[ expre1 -a expre 2 ]与[[ expre1 && expre2 ]]并非完全一致,&&会进行逻辑短路操作,而-a并不会

[root@mghuee~chunlanyy testdir]# [  -gt  -a  > test1.txt ] && echo yes || echo no
no
[root@mghuee~chunlanyy testdir]# ls
test1.txt
并未进行逻辑短路操作,执行所有判断,即使"1 -gt 3"已经错误,依旧执行后续操作,虽然结果为no,但是还会生成test1.txt文件
[root@mghuee~chunlanyy testdir]# [[  -gt  &&  > test2.txt ]] && echo yes || echo no
no
[root@mghuee~chunlanyy testdir]# ls
test1.txt

进行逻辑运算操作,在与命令中,"1 -gt 3"为false即不作后续判断,故无test2.txt的出现

3."[]"是命令,故在其中的变量引用或常量,需使用双引号或者单引号括起来,因为会出现单词分割(Word-Splitting)现象

[root@mghuee~chunlanyy testdir]# I="";[ -f $I ] && echo yes || echo no
no
[root@mghuee~chunlanyy testdir]# I="";[ -f "$I" ] && echo yes || echo no
yes
[root@mghuee~chunlanyy testdir]# ll -a
total
drwxr-xr-x. root root Jun : .
drwxrwxrwt. root root Jun : ..
-rw-r--r--. root root Jun :

在当前目录中存在一个文件名为" 29"的文件(29前面有空格),在[]中未对引用变量加入双引号时,[]内部执行判断为-f "29",因为当前目录中不存在文件名的"29"的文件,显示结果是No

四.(())

支持四则运算,等同于let功能

[root@mghuee~chunlanyy testdir]# let I=+;echo $I

[root@mghuee~chunlanyy testdir]# I=$((+));echo $I

五.[[]]

"[["也是一个keyword,用于比较判断,基本支持"[]"中所有的判断比较符。

[root@mghuee~chunlanyy testdir]# type [[
[[ is a shell keyword

"[["和"["的不同点:

1.逻辑运算符不一致,"[[]]"为"&&"、"||","[]"为"-a"、"-o"。"[[]]"支持逻辑短路,而"[]"不支持

2."[[]]"支持正则表达式的匹配。

3."[[]]"为一个keyword,同括号与表达式中间必须要有空格进行隔离

4."[[]]"中使用比较符时不能转义,同时不会出现Word-Splitting

[root@mghuee~chunlanyy testdir]# I="";[[ -f $I ]] && echo yes || echo no
yes
[root@mghuee~chunlanyy testdir]# ll -a
total
drwxr-xr-x. root root Jun : .
drwxrwxrwt. root root Jun : ..
-rw-r--r--. root root Jun :

与上述"[]"的结果进行比较,很显然,在"[[]]"中并不会出现Word-Splitting

[root@mghuee~chunlanyy testdir]# [[ a >  ]] && echo yes || echo no
yes
[root@mghuee~chunlanyy testdir]# [[ a \> ]] && echo yes || echo no
-bash: conditional binary operator expected
-bash: syntax error near `\>'

可以看出,使用转义后出现error

5.[[]]中"=="与"=~"的使用

引用《advanced bash-scripting guide》对两者的解释

== String comparison operator   <==字符串比较

=~ Regular Expression match operator  <==正则表达式匹配

但是在此也并非代表"=="在"[[]]"中不能实现正则表达式模式的匹配,也能实现部分的匹配

[root@mghuee~chunlanyy tmp]# [[ abc == a*b***c ]] && echo yes || echo no
yes

但只能实现字符之间的匹配

[root@mghuee~chunlanyy tmp]# [[ `cat /etc/passwd` == ^root ]] && echo yes || echo no
no
[root@mghuee~chunlanyy tmp]# [[ `cat /etc/passwd` =~ ^root ]] && echo yes || echo no
yes

而"=~"则能完整的按正则表达式去匹配

注意:在正则表达式模式匹配中,右边的匹配模式不能使用双引号,在bash 3.2版本之后已经明确说明在使用正则表达式时所匹配的模式不能加上双引号

[root@mghuee~chunlanyy tmp]# [[ `cat /tmp/` =~ "^root" ]] && echo yes || echo no
yes
[root@mghuee~chunlanyy tmp]# cat
"^root"
[root@mghuee~chunlanyy tmp]# [[ `cat /tmp/` =~ ^root ]] && echo yes || echo no
no
[root@mghuee~chunlanyy tmp]# cat
"^root"

因为在"[[]]"不会出现Word-Splitting,加入后反而让上匹配模式变成了“"^root"”

小结:

  1. 进行算术运算时使用"let命令",或者"$(())""
  2. 进行文件存在或者字符是否为空时使用"[]"
  3. 逻辑运算符"&&"、"||"要在"[[]]"中使用,"-a"、"-o"在"[]"中使用
  4. 在"[[]]"中使用正则表达式进行匹配的时候所匹配模式不能使用双引号
  5. 数值大小比较时在"[]"中进行比较,要使用"-lt"、"-gt"这样的比较符,不能使用"<"、">"
  6. "[[]]"与"[]"两边最好都保持空格,"[[]]"是两边一定要有空格进行隔离
  7. 以上均为习惯使用方式,并非说明其它组合模式一定不可使用,但可避免出现一些让人费解的错误

bash中(),{},(()),[],[[]]的区别的更多相关文章

  1. read name 和 read 在 Bash 中的区别

    read 带一个参数和不带参数的区别是什么,我本以为仅仅是被赋值的变量的名字不同而已: $ read name 1 $ echo "$name" 1 $ read 1 $ echo ...

  2. bash中的set, env, export unset的区别

    参考这篇文章很好 参考这篇文章2 -------------------------- == set显示的是当前shell的变量, 不同的shell, 它的私有变量是不同的 env是显示用户的变量, ...

  3. Bash中的任务(job)管理

    本来不准备写这篇博客的,因为任务管理(job管理)非常非常常用,以至于觉得根本没有必要去写这样一个东西.但想了下,还是记录一下吧,也许有人会用到呢. 不知你是否碰到过这样的情况,当你兴致勃勃的打开VI ...

  4. shell脚本中的[]/[[]]区别

    转自:http://www.cnblogs.com/include/archive/2011/12/09/2307905.html 引用: http://www.51testing.com/?uid- ...

  5. Bash中的位置参数和特殊参数

    #Bash中的位置参数和特殊参数 #Bash中的位置参数是由0以外的一个或多个数字表示的参数.#位置参数是当Shell或Shell函数被引用时由Shell或Shell函数的参数赋值,并且可以使用Bas ...

  6. bash中 2>&1 & 的解释

    1.首先,bash中0,1,2三个数字分别代表STDIN_FILENO.STDOUT_FILENO.STDERR_FILENO,即标准输入(一般是键盘),标准输出(一般是显示屏,准确的说是用户终端控制 ...

  7. bash 中 () {} [] [[]] (()) 的解释

    bash 中 () {} [] [[]] (()) 的解释 来源  https://www.cnblogs.com/fhefh/archive/2011/04/16/2017895.html bash ...

  8. 『忘了再学』Shell基础 — 9、Bash中的特殊符号(一)

    目录 1.双单引号 2.双引号 3.$符号 4.反引号 5.$()符号 6.#符号 7.\符号 1.双单引号 '':单引号.在单引号中所有的特殊符号,如$和"`"(反引号)都没有特 ...

  9. 『忘了再学』Shell基础 — 10、Bash中的特殊符号(二)

    提示:本篇文章接上一篇文章,主要说说()小括号和{}大括号的区别与使用. 8.()小括号 ():用于一串命令执行时,()中的命令会在子Shell中运行.(和下面大括号一起说明) 9.{}大括号 {}: ...

随机推荐

  1. 身份证识别OCR,开启视频模式扫一扫即可识别身份证信息

    文章摘要:身份证识别等证件识别OCR技术在各个行业得到广泛应用,例如:车险移动查勘会用到身份证识别.行驶证识别.车架号识别: 寿险移动展业会用到名片识别.银行卡识别:电信实名制代理网点采集身份证信息会 ...

  2. MVC之前-ASP.NET初始化流程分析1

    Asp.net Mvc是当前使用比较多的web框架,也是比较先进的框架.我打算根据自己的实际项目经验以及相关的源码和一些使用Asp.net Mvc的优秀项目(主要是orchard)来说一说自己对于As ...

  3. Reids命令解析-RENAME

    有一天开发突然照过来问,维萨我这个Redis实例这么慢呢?为什么这么慢,于是连上实例SLOWLOG 一看,这些慢日志都是大部分是RENMAE操作导致的,可是为什么RENAME操作会慢呢?不就是改个名字 ...

  4. Struts2教程

    一.初识Struts2 Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的 ...

  5. 【Android Developers Training】 33. 接收来自其它应用的简单数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. java怎么连接mysql数据库

    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口 ...

  7. eclipse 导入git库 Android工程

    1. 导入git库 1.1 从git库 clone 代码 在file->import中选中Git 目录下的Projects from Git 点击Next 选择 URL 点击Next 输入URL ...

  8. ASP.NET MVC Autofac依赖注入的一点小心得(包含特性注入)

    前言 IOC的重要性 大家都清楚..便利也都知道..新的ASP.NET Core也大量使用了这种手法.. 一直憋着没写ASP.NET Core的文章..还是怕误导大家.. 今天这篇也不是讲Core的 ...

  9. MyBatis源码解析【1】准备工作

    终于迎来了这一天,我觉得现在的我在经历了长时间的学习和开发之后有了一定的经验,所以准备开始学习源码. 今天我将做好充足的准备,在接下来的一个月中,努力的爬过这座大山.(可能不用一个月,但是我觉得需要仔 ...

  10. .net 实现aop的三种方法。

    动态代理 透明代理 编译时注入