19.2. 通配

Bash本身没有正则表达式的功能.在脚本里,使用正则表达式的是命令和软件包 -- 例如sedawk -- 它们可以解释正则表达式.

Bash所做的是展开文件名扩展 [1] -- 这就是所谓的通配(globbing) -- 但它不是使用标准的正则表达式. 而是使用通配符. 通配解释标准的通配符:*和?, 方括号括起来的字符,还有其他的一些特殊的字符(比如说^用来表示取反匹配).然而通配机制的通配符有很大的局限性. 包含有*号的字符串将不会匹配以点开头的文件,例如.bashrc. [2] 另外,通配机制的? 字符和正则表达式中表示的意思不一样.

 bash$ ls -l
 total 2
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 a.1
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 b.1
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 c.1
 -rw-rw-r--    1 bozo  bozo       466 Aug  6 17:48 t2.sh
 -rw-rw-r--    1 bozo  bozo       758 Jul 30 09:02 test1.txt
 
 bash$ ls -l t?.sh
 -rw-rw-r--    1 bozo  bozo       466 Aug  6 17:48 t2.sh
 
 bash$ ls -l [ab]*
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 a.1
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 b.1
 
 bash$ ls -l [a-c]*
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 a.1
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 b.1
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 c.1
 
 bash$ ls -l [^ab]*
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 c.1
 -rw-rw-r--    1 bozo  bozo       466 Aug  6 17:48 t2.sh
 -rw-rw-r--    1 bozo  bozo       758 Jul 30 09:02 test1.txt
 
 bash$ ls -l {b*,c*,*est*}
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 b.1
 -rw-rw-r--    1 bozo  bozo         0 Aug  6 18:42 c.1
 -rw-rw-r--    1 bozo  bozo       758 Jul 30 09:02 test1.txt
 	      

Bash会对命令行中没有引号引起来的字符尝试文件名扩展. echo 命令可以印证这一点.

 bash$ echo *
 a.1 b.1 c.1 t2.sh test1.txt
 
 bash$ echo t*
 t2.sh test1.txt
 	      

Note

可以改变Bash对通配字符进行解释的行为. set -f 命令可以禁止通配机制, 并且shopt的选项nocaseglobnullglob 能改变通配的行为.

参考例子 10-4.

[1]

文件名扩展意思是扩展包含有特殊字符的文件名模式和模板. 例如,example.???可能扩展成example.001和/或example.txt.

[2]

文件名扩展能匹配点开头的文件,但仅在模式字串明确地包含字面意思的点(.)时才扩展.
   1 ~/[.]bashrc    #  不会扩展成 ~/.bashrc
   2 ~/?bashrc      #  也不会扩展.
   3                #  通配机制中的通配符和元字符不会扩展点文件
   4                #
   5 
   6 ~/.[b]ashrc    #  会扩展成 ~/.bashrc
   7 ~/.ba?hrc      #  也会.
   8 ~/.bashr*      #  也会.
   9 
  10 # 可以使用"dotglob"选项把这个特性禁用.
  11 
  12 # 多谢, S.C.