()小括号,{}大括号,反引号

-- TOC --

本文尝试总结bash脚本中()小括号,{}大括号和反引号``的使用方法。

执行命令

大小括号和反引号,均可以用来执行命令。

(cmd),表示用一个bash子进程来执行cmd,如果cmd是一个命令,末尾可以没有分号[;]。

{ cmd;},表示在当前bash进程中执行cmd,cmd与左边的{之间必须要有空格,cmd必须要用分号结尾。(只是不创建subshell子进程,并不表示不创建cmd进程)

这两种特性叫做grouping command,区别是是否创建subshell进程,以及书写格式。还可以跨行写:

$ cat test.sh
echo '123' && 
{
    echo 'a'
    echo 'b'
}

var=$(cmd),这种用法很常见,表示在子shell进程中执行cmd,并将输出字符串赋值给变量var。

反引号``,也是用来在子进程中执行命令,不过建议使用小括号,可读性好,不容易看花眼:

$ echo `ls`
aa ab a.out cc hello_driver.c makefile test.a test.b test.c
$ a=`ls`
$ echo $a
aa ab a.out cc hello_driver.c makefile test.a test.b test.c

大括号引用变量

在脚本中,常见的对变量的引用是这样的:${ABC},当然也可以写成 $ABC,两边加上大括号,是为了确定变量的边界,以免出现歧义。

$ ABC='abc'
$ echo $ABC
abc
$ echo ${ABC}12345
abc12345

不仅仅是确认变量名称的边界,还可以对变量进行很多扩展操作。

大括号补全扩展

可以把大括号里的内容,看作是一种(多)补全扩展。

$ echo {1..6}
1 2 3 4 5 6
$ echo {1,3,5}
1 3 5
$ echo {1..9..2}
1 3 5 7 9
$ echo {a,b,c,d,e}
a b c d e
$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {9..1}
9 8 7 6 5 4 3 2 1
$ echo {z..a}
z y x w v u t s r q p o n m l k j i h g f e d c b a
$ echo {0..-9}
0 -1 -2 -3 -4 -5 -6 -7 -8 -9
$ echo {-9..0}
-9 -8 -7 -6 -5 -4 -3 -2 -1 0

看起来天然就适合用来处理循环:

$ for i in {1..5}; do
> echo $i
> done
1
2
3
4
5

处理多个名称有规律的文件:

$ touch test{1..5}
$ ls test*
test1  test2  test3  test4  test5
$ touch abc{1,3,5}
$ ls abc*
abc1 abc3 abc5
$ touch doc{.jpg,.png,.txt}
$ ls doc*
doc.jpg doc.png doc.txt
$ #...
$ rm test{1..5}
$ rm abc{1,3,5}
$ rm doc{.jpg,.png,.txt}

多重循环扩展:

$ echo {a..c}{1..5}
a1 a2 a3 a4 a5 b1 b2 b3 b4 b5 c1 c2 c3 c4 c5
$ echo {a,b}{1,3}c
a1c a3c b1c b3c
$ echo {a,b}{1,2}{x,y}
a1x a1y a2x a2y b1x b1y b2x b2y

多个连续循环扩展:

$ echo {{1..3},{a..c}}
1 2 3 a b c
$ echo {{1..3},{a..c}}xy
1xy 2xy 3xy axy bxy cxy
$ echo {{1..3},{a..c}}{r,t}
1r 1t 2r 2t 3r 3t ar at br bt cr ct
$ echo {{1..3},{6,7,8}{x,y},{a..c}}
1 2 3 6x 6y 7x 7y 8x 8y a b c

glob规则里也有[]扩展,与{}有类似的地方。由于大括号扩展{...}不是文件名扩展,所以它总是会扩展的。这与方括号扩展[...]完全不同,如果匹配的文件不存在,方括号就不会扩展。这一点要注意区分。还要,大括号表示范围用..,方括号表示范围用-

双重小括号执行四则运算和逻辑运算

在bash命令行中用双重小括号的特点:

  1. 在双括号结构中,所有表达式可以像c语言一样,如:a++,--b等。
  2. 在双括号结构中,变量的引用可以不使用$前缀。
  3. 双括号内可以进行逻辑运算,四则运算。
  4. 双括号结构 扩展了for,while,if条件测试运算。
  5. 支持多个表达式运算,各个表达式之间用,分开。

可以不用let,expr命令了。

$ a=1
$ echo $((a++))
1
$ echo $a
2
$ b=10
$ echo $((a++,--b))
9
$ echo $a $b
3 9
$ echo $((a>3?a:b))
9
$ ((a>1)) && echo 'a>3 is true'
a>3 is true
$ if ((a>1)); then
> echo 'haha..'
> fi
haha..

((...))语法支持的算术运算符如下:

更多在命令行做计算的示例代码:

$ # 赋值变量
$ ((foo = 5 + 5))
$ echo $foo
10
$ # 忽略内部空格
$ ((2+2))
$ (( 2+2 ))
$ (( 2 + 2 ))
$ # 只要结果不是0,就算成功
$ (( 3 + 2 ))
$ echo $?
0
$ # 结果是0,失败
$ (( 3 - 3 ))
$ echo $?
1
$ # 内部还能用括号,实现四则运算
$ echo $(( (2 + 3) * 4 ))
20
$ # 等价
$ echo $(((5**2) * 3))
75
$ echo $(($((5**2)) * 3))
75
$ # 报错,只能计算整数!!
$ echo $((1.5 + 1))
bash: 语法错误
$ # $[...]是以前的语法,也可以做整数运算,不建议使用
$ echo $[3+5]
8
$ # 16,8,2进制
$ echo $((0xFF))
255
$ echo $((077))
63
$ echo $((2#11111111))
255

本文链接:https://cs.pynote.net/sf/linux/shell/202110285/

-- EOF --

-- MORE --