glob 模式介绍
[TOC]
本文介绍 shell 中的 glob 模式, 一种简化的正则表达式规则, 常用于匹配各种路径.
glob 模式 最初是贝尔实验室 Unix V6 系统上的一个 /etc/glob
的命令(全称: globbing pathnames. 详见 man 文档), 用于展开命令行中的通配符. 成为 shell 内建的命令. 系统也提供了该功能的 C 语言库函数glob()
(名为 glob(3)
).
基础语法
相比正则表达式大量的元字符, glob 模式中元字符极少, 所以掌握起来也很快. glob 默认不匹配隐藏文件(以点.
开头的文件或目录), 下面是 glob 的语法:
通配符 | 描述 | 示例 | 匹配 | 不匹配 |
---|---|---|---|---|
* |
匹配0个或多个字符, 包含空串 | Law* |
Law , Laws 和Lawer |
La , aw |
? |
匹配1个字符 | ?at |
cat , bat |
at |
[abc] |
匹配括号内字符集合中的单个字符 | [][!]at |
!at |
[at] , at , at! |
[a-z] |
匹配括号内字符范围中的单个字符 | [a-z]at |
aat , bat , zat |
at , bcat , Bat |
[^abc] 或[!abc] |
匹配非括号内字符集合中的单个字符 注意 ^ 是不符合 POSIX 标准的. |
[!CB]at |
cat , bat |
Cat , Bat |
[^a-z] 或[!a-z] |
匹配非括号内字符范围中的单个字符 注意 ^ 是不符合 POSIX 标准的. |
[!A-Z]at |
aat , bat , zat |
Aat , Bat , Zat |
一些注意项:
转义: 放在
""
或者''
中间的*
会被转义成只匹配*
字符本身, 失去其通配符的特性. 例如:cp -r ${PATH}"/a/*" .
找到的目录只会去匹配名为*
的目录. 如果想要实线其通配符效果, 不能对其转义, 例如:cp -r ${PATH}"/a/"* .
除了''
以及""
还可以使用\
进行转义.
在 bash 命令行中
[!abc]
需要转义成[\!abc]
.
这些通配符不能被
()
包裹. 否则失去通配符的意义.
[]
的-
range 规则是基于 ASCII 码的(一般而言, 有些平台也许有自己的序列定义, 可以通过LC_COLLATE
变量用locale
命令查看), 换句话说, 只要是在 ASCII 码内的连续序列都可以成为匹配 range. 例如[--0]
匹配-
,.
,0
, ASCII 码中的序列如下表, 但是/
转义符是个例外不在其列.
二进制 | 十进制 | 十六进制 | ASCII 字符/缩写 |
---|---|---|---|
00101101 | 45 | 2D | - |
00101110 | 46 | 2E | . |
00101111 | 47 | 2F | / |
00110000 | 48 | 30 | 0 |
如上面的 range 匹配语法. 目录的
/
无法被*
,?
,[.-0]
匹配, 必须显式地写出/
进行匹配.
注意
.
开头的文件无法被*
,?
, 匹配, 例如rm *
不会去删除.profile
文件. 如果想删除所有的隐藏文件可以使用命令rm .*
, 此命令不会去删除.
..
两个隐藏目录, 即便是加上-r
参数也不行, 如果也想删除这两个文件只能删除整个目录.
与正则表达式 regexp 的差异
glob 模式主要用于匹配文件路径, 当然也可以用于匹配字符串, 不过在匹配字符串的能力上比 regexp 要弱很多. 因此 glob 模式通常用来匹配目录以及文件, 而不是文本. 由于 glob 模式和 regexp 存在相同的元字符, 但是含义却不同, 容易导致混淆, 为了避免混淆, 下面将 glob 模式转换成对应的 regexp 表示, 以便区分他们的异同点.
glob | regexp | 精确的 regexp |
---|---|---|
* |
.* |
^(?!\.)[^\/]*?$ |
? |
. |
^(?!\.)[^\/]$ |
[a-z] |
[a-z] |
^[a-z]$ |
glob 匹配的是整个字符串, 而 regexp 默认匹配的是子串, regexp 如果要匹配整个字符串需显式指定
^
和$
. 正则表达式中的(?!\.)
, 其表示不匹配隐藏文件
扩展语法
除了基础语法外, bash 还支持 glob 的一些扩展语法, 主要包含三种:
- Brace Expansion
- globstar
- extglob
三种扩展语法的定义和描述如下:
通配符 | 描述 | 示例 | 匹配 | 不匹配 |
---|---|---|---|---|
{x, y, ...} |
Brace Expansion, 展开花括号内容, 支持展开嵌套括号 | a.{png,jp{,e}g} |
a.png , a.jpg , a.jpeg |
|
** |
globstar, 匹配所有文件和任意层目录, 如果** 后面紧接着/ 则只匹配目录, 不含隐藏目录 |
src/** |
src/a.js , src/b/a.js , src/b/ |
src/.hide/a.js |
?(pattern-list) |
匹配0次或1次给定的模式 | a.?(txt|bin) |
a. , a.txt , a.bin |
a |
*(pattern-list) |
匹配0次或多次给定的模式 | a.*(txt|bin) |
a. , a.txt , a.bin , a.txtbin |
a |
+(pattern-list) |
匹配1次或多次给定的模式 | a.+(txt|bin) |
a.txt , a.bin , a.txtbin |
a. , a |
@(pattern-list) |
匹配给定的模式 | a.@(txt|bin) |
a.txt , a.bin |
a. , a.txtbin |
!(pattern-list) |
匹配非给定的模式 | a.!(txt|bin) |
a. , a.txtbin |
a.txt , a.bin |
pattern-list 是一组以
|
作为分隔符的模式集合, 例如abc|a?c|ac*
注意: 在使用花括号
{}
的时候, 里面的单个字符串需要使用单引号或者双引号括住, 否则就会视为多个的单个字符. 同时, 它适用于多个匹配, 如果硬要进行单个匹配必须显式指明其他的为空, 例如,ls :{"src",}
,,
后为空, 只匹配src
一个目录.
在使用通配符的过程中可能会遇到文件名中包含了特殊字符的情况. 可以使用专用字符集(下面介绍)匹配, 也可以使用转义或者使用引号来匹配(可以少打一些字符).
例如文件 a␣.sh
(␣
符号表示空格)的匹配:
1 | $ cat *[[:space:]].sh #专用字符集匹配 |
专用字符集
字符 | 意义 |
---|---|
[:alnum:] | 任意数字或者字母 |
[:alpha:] | 任意字母 |
[:space:] | 空格 |
[:lower:] | 小写字母, 等效于 [a-z] |
[:digit:] | 任意数字 |
[:upper:] | 任意大写字母 |
[:cntrl:] | 控制符 |
[:graph:] | 图形 |
[:print:] | 可打印字符 |
[:punct:] | 标点符号 |
[:xdigit:] | 十六进制数 |
[:blank:] | 空白字符(未验证) |
注意: 在使用专属字符集的时候, 字符集之外还需要用
[ ]
来包含住, 否则专用字符集不会生效, 例如[[:space:]]
.使用专用字符集的意义, 例如与其使用
[a-z]
而是使用[:lower:]
, 是因为一些语言中小写字母不仅仅只包含英语的小写字母, 例如德语系里面的ä
.
需要转义的 Linux shell 元字符
字符 | 作用 |
---|---|
IFS | 由 < space > 或 < tab > 或 < enter > 三者之一组成 |
CR | 由 < enter > 产生 |
= | 设定变量 |
$ | 作变量或运算替换 |
> | 重导向标准输出 |
< | 重导向标准输入 |
| | 命令管线 |
& | 重导向文件描述符, 或将命令静默执行 |
( ) | 将其内的命令置于 nested subshell 执行, 或用于运算或命令替换 |
{ } | 将其内的命令置于 non-named function 中执行, 或用在变量替换的界定范围 |
; | 在前一个命令结束时, 而忽略其返回值, 继续执行下一个命令 |
&& | 在前一个命令结束时, 若返回值为 true, 继续执行下一个命令 |
|| | 在前一个命令结束时, 若返回值为 false, 继续执行下一个命令 |
! | 执行 history 中的命令 |
Collating symbols and equivalence classes–不常用
用来匹配一些语言中的字符.
字符 | 例子 | 作用 |
---|---|---|
[. .] |
[.ch.] |
a collating element defined for the current locale. |
[= =] |
[[=a=]] |
[aáaäâ] |
参考链接:
https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching
https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html#Brace-Expansion