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
