> 编写shell脚本时,通配符可以用于文件名扩展或用于正则表达式。
## 文件名扩展(globbing)
文件名扩展中的两个关键字符是问号`?`与星号`*`。问号匹配任意单个字符,星号匹配任意字符序列。因为`*`匹配任意字符序列,所以也可以匹配空字符。而问号不同,它必须总是匹配一个字符。通配符可以位于任意位置。
尽管`?`和`*`是文件名扩展的两个主要元字符,但还有`[...]`这样的结构。可以用它来表示范围,如`[a-z]`指定范围为a~z之间的字母。范围可以任意选择,但`[a-z]`与`[0-9]`使用得最多。另外还有一些定义好的类能用来代替这两个范围,并且意义相同。`[a-z]`等同于`[[:alpha:]]`,`[0-9]`等同于`[[:digit:]]`。全部的可用类如下表:
|类|成员|
|--|--|
|alnum|A-Z、a-z、0-9|
|alpha|A-Z、a-z|
|blank|空格和制表符|
|cntrl|ASCII字符0-31(非打印控制字符)|
|digit|0-9|
|graph|A-Z、a-z、0-9与标点符号|
|lower|a-z|
|print|ASCII字符32-127(可打印字符)|
|punct|标点符号(A-Z、a-z和0-9意外的可打印字符)|
|space|空格、制表符、LF(10)、VT(11)、FF(12)、CR(13)|
|upper|A-Z|
|xdigit|0-9、A-F、a-f|
### bash的文件名扩展特性
bash指令`set -o noglob`或者`set -f`都可以将文件名扩展功能关闭。`set +o noglob`或`set +f`重新开启。
### shell选项
shell选项改变shell的工作方式。shell的有些选项会影响到文件名扩展。分别使用命令`shopt -s optionname `与`shopt -u optionname`来设置与取消选项。如果要使用某个shell选项,可以使用`shopt optionname`查询是否设置,或者按照编程的方法使用`shopt -q optionname`。该命令不显示任何输出,但如果选项被设置则返回0,否则返回1。
shell最强大的选项是extglob。整套extglob通配符如下表:
|模式|匹配|
|--|--|
|?(模式列表)|0或1个模式|
|*(模式列表)|0或多个模式|
|+(模式列表)|1或多个模式列表|
|@(模式列表)|1个模式|
|!(模式列表)|除了一个模式以外的任何模式|
## 正则表达式和引用
### 正则表达式概述
正则表达式本身与shell没有直接关系,除了bash的`=~`语法,只有像grep、sed和awk这样的外部工具才使用正则表达式。因为shell扩展与正则表达式使用的语法非常相似,所以从shell传递给外部命令的正则表达式可能会在中途被shell解析。
### 引用
从shell向外部命令传递参数的方式非常重要。有3种主要形式的引用——单引号、双引号以及反斜线。
### 单引号
单引号可以防止shell解释其中的内容。shell分析的只是与第一个单引号配对的下一个单引号。单引号中,所有字符按字面意义进行处理,包括双引号。引号自身被忽略,其中的空格将被保留,引号中的变量引用被看成是字符串:
```shell
$ hello=hi~
$ echo '$hello world'
$hello world
```
### 双引号
用双引号引用,有部分字符会被shell解释,而不是全部。双引号中,单引号被当成常规字符。其中的变量引用被解释,但文件名不会被扩展,单引号也被保留:
```
$ hello=hi~
$ echo "$hello world.Things '*'"
hi~ world.Things '*'
```
### 反斜线
当需要在常规字符串中包含特殊字符,但它又会被shell解释的时候,可以在字符前加上反斜线`'\'`。可以使用反斜线进行转移的字符有:
* 分号`';'`,一般被shell用于在一行内组合多条命令
* 感叹号`'!'`,用于回调历史命令
* `'&'`符号,用于在后台运行进程
* 在花括号扩展中,特殊符号`'{'`、`'}'`和`','`可以通过反斜线转义得到。
* 另外,还可以对命令行中的反斜线本身进行转义`'\\'`
反斜线还能用于续行。一个很长的命令会很难读懂,所以最好选一个位置进行换行。如果一行代码以反斜线结尾,并且紧跟反斜线之后的是换行符,则在解释时反斜线与换行符都会被去掉。