[转帖]bash中(),{},(()),[],[[]]的区别

https://www.cnblogs.com/marility/p/7259821.html

差之毫厘谬以千里 

需要仔细认真

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

一.()

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

[[email protected]~chunlanyy testdir]# I=123;(I=xyz;echo $I;);echo $I
xyz
123

二.{}

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

[[email protected]~chunlanyy testdir]# I=123;(echo $I;I=xyz;echo $I;);echo $I
123
xyz
123
[[email protected]~chunlanyy testdir]# I=123;{ echo $I;I=xyz;echo $I; };echo $I
123
xyz
xyz

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

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

[[email protected]~chunlanyy testdir]# type {
{ is a shell keyword

三.[]

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

[[email protected]~chunlanyy testdir]# type [
[ is a shell builtin

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

[[email protected]~chunlanyy testdir]# [ 4 -lt 3 ] && echo yes || echo no
no
[[email protected]~chunlanyy testdir]#  test 4 -lt 3  && 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这样的比较符,而不能使用"<"这样的比较符,即便是加了转义符的"\<"

[[email protected]~chunlanyy testdir]# [ 1 > 2 ] && echo yes || echo no
yes

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

[[email protected]~chunlanyy testdir]# ll -l
total 0
-rw-r--r--. 1 root root 0 Jun 17 20:53 2

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

[[email protected]~chunlanyy testdir]# [ 1 \> 2 ] && echo yes || echo no
no

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

[[email protected]~chunlanyy testdir]# [ a \> 2 ] && echo yes || echo no
yes

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

[[email protected]~chunlanyy testdir]# [ 5 \> 20 ] && echo yes || echo no
yes

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

[[email protected]~chunlanyy testdir]# [ 1 -lt  2 && 1 -lt 3 ] && echo yes || echo no
-bash: [: missing `]‘
no

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

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

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

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

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

[[email protected]~chunlanyy testdir]# I=" 29";[ -f $I ] && echo yes || echo no
no
[[email protected]~chunlanyy testdir]# I=" 29";[ -f "$I" ] && echo yes || echo no
yes
[[email protected]~chunlanyy testdir]# ll -a
total 8
drwxr-xr-x. 2 root root 4096 Jun 17 23:20 .
drwxrwxrwt. 6 root root 4096 Jun 17 20:53 ..
-rw-r--r--. 1 root root    0 Jun 17 23:17  29

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

四.(())

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

[[email protected]~chunlanyy testdir]# let I=2+4;echo $I
6
[[email protected]~chunlanyy testdir]# I=$((2+4));echo $I
6

五.[[]]

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

[[email protected]~chunlanyy testdir]# type [[
[[ is a shell keyword

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

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

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

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

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

[[email protected]~chunlanyy testdir]# I=" 29";[[ -f $I ]] && echo yes || echo no
yes
[[email protected]~chunlanyy testdir]# ll -a
total 8
drwxr-xr-x. 2 root root 4096 Jun 17 23:20 .
drwxrwxrwt. 6 root root 4096 Jun 17 20:53 ..
-rw-r--r--. 1 root root    0 Jun 17 23:17  29

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

[[email protected]~chunlanyy testdir]# [[ a > 1 ]] && echo yes || echo no
yes
[[email protected]~chunlanyy testdir]# [[ a \> 1 ]] && 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  <==正则表达式匹配

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

[[email protected]~chunlanyy tmp]# [[ abc == a*b***c ]] && echo yes || echo no
yes

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

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

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

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

[[email protected]~chunlanyy tmp]# [[ `cat /tmp/123` =~ "^root" ]] && echo yes || echo no
yes
[[email protected]~chunlanyy tmp]# cat 123
"^root"
[[email protected]~chunlanyy tmp]# [[ `cat /tmp/123` =~ ^root ]] && echo yes || echo no
no
[[email protected]~chunlanyy tmp]# cat 123
"^root"

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

小结:

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

原文地址:https://www.cnblogs.com/jinanxiaolaohu/p/12166118.html

时间: 2024-10-10 20:56:16

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

bash中的正则工具几种引用方式的区别

在平时大量的日志数据分析时候,我们就会大量的使用正则表达式用来配合平时写的脚本来带来需要的效果,而在使用正则表达式工具的时候都是在需要在引用中,在平时我们的引用一般有3中,分别是:双引号("").单引号('').反引号(``). 其中最后一种和前2种区分还是比较简单的,反引号(``)的引用在bash中一般是用来做参数展开,用于获取最后参数运算后的结果用的,而双引号("").单引号('')这2种区别还是有点不好区分的,记得以前还有朋友来问过我,在这里就简单的说一下,从

bash中 2&gt;&amp;1 &amp; 的解释

1.首先,bash中0,1,2三个数字分别代表STDIN_FILENO.STDOUT_FILENO.STDERR_FILENO,即标准输入(一般是键盘),标准输出(一般是显示屏,准确的说是用户终端控制台),标准错误(出错信息输出). 2.输入输出可以重定向,所谓重定向输入就是在命令中指定具体的输入来源,譬如 cat < test.c 将test.c重定向为cat命令的输入源.输出重定向是指定具体的输出目标以替换默认的标准输出,譬如ls > 1.txt将ls的结果从标准输出重定向为1.txt文本

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

转自:http://www.cnblogs.com/include/archive/2011/12/09/2307905.html 引用: http://www.51testing.com/?uid-7701-action-viewspace-itemid-13731 http://blog.csdn.net/sunboy_2050/article/details/6836382 shell 括号 学习shell的时候总是被shell里的条件判断方式搞得头疼,经常不知道改 用[],[[]],((

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

#Bash中的位置参数和特殊参数 #Bash中的位置参数是由0以外的一个或多个数字表示的参数.#位置参数是当Shell或Shell函数被引用时由Shell或Shell函数的参数赋值,并且可以使用Bash的内部命令set来重新赋值.位置参数N可以被引用为${N},或当N只含有一个数字时被引用为$N # $ set 1 2 3 four five six 7 8 9 ten# $ echo "$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}"# 1 2 3 four fiv

Bash中的单双引号作用

shell中的输入的字符分为纯字符和元字符(特殊意义的字符 meta) 元字符: IFS:由 <space> 或 <tab> 或 <enter> 三者之一组成(我们常用 space ). CR:由 <enter> 产生. =:设定变量. $:作变量或运算替换(请不要与 shell prompt 搞混了). >:重导向 stdout. <:重导向 stdin. |:命令管线. &:重导向 file descriptor ,或将命令置于背境执

[Linux]Bash中的任务(job)管理

?? 本来不准备写这篇博客的,因为任务管理(job管理)非常非常常用,以至于觉得根本没有必要去写这样一个东西.但想了下,还是记录一下吧,也许有人会用到呢. 不知你是否碰到过这样的情况,当你兴致勃勃的打开VIM,写代码写到正酣时,运营MM或者产品MM气喘吁吁的跑过来:"赶紧帮我跑一下xx的数据,一会做PPT要用".可是不想直接关闭当前的VIM,而且某些系统下,又不能新开tty(如设置了maxlogins参数)去执行这些任务,这可怎么办?这其实就涉及到了任务(job)管理. 那么什么是任务

bash中通过设置PS1变量改变提示符颜色

参考 <Prompt Magic> ubuntu初始时bash提示符的颜色同程序输出的颜色相同,当大量有输出时,找到输出信息开始的地方往往很费劲.如果把提示符的颜色变成更为醒目的颜色,那么就很容易定位输出信息开始处.bash中想要改变提示符颜色可以通过PS1变量的值来设置,如果将其放入用户对应目录下的.bashrc文件中,则用户打开bash时自动更改颜色.这里,我将提示符改成绿色:    PS1="\[\e[32m\]\[email protected]\h:\w\$ \[\e[0m

bash中的变量

1.bash中的变量: #命令set:显示所有变量. (1).本地变量:只对当前shell进程有效,对其子shell以及其它shell都无效. 定义本地变量:[set]变量名="Value",例animal=dog 引用本地变量:${变量名},其中{}通常省略,例echo $animal 撤销本地变量:unset 变量名,例unset animal (2).局部变量:只对局部代码有效 定义局部变量:local 变量名=变量值 (3).环境变量:当前shell进程以及其子shell都有效

Bash中的数学扩展

Bash只支持整数运算,不支持浮点运算.如果需要进行浮点运算,需要使用bc程序.Bash中的数学扩展有两种形式:$[ expression ]或$(( expression )) 例子:$echo $[5+4-2]7 $echo $[ 5*(6-2) ]20 var1=100var2=50var3=45var4=$((var1*(var2-var3))) #注意:圆括号里不需要加$了,和数学运算一样,推荐用这种方式$echo $var4 也可以使用程序/usr/bin/expr来进行整数运算$e