Quan Zhuo's Blog

通配符和正则表达式

2016-06-28

通配符和正则表达式在命令行以及文本处理方面非常有用。当在命令行工作时,使用通配符扩展文件名; 当使用 grep, awk, sed 等处理文本时,使用正在表达式匹配文本。 这里做一下总结: 通配符用于路径名扩展,而正则表达式用于文本匹配

通配符

很久以前,在 Unix V6 中,有一个程序 /etc/glob 可以展开 通配符模式(wildcard pattern)。 后来这就成了一个 shell 内建的特性。而且还有一个 glob 库供用户编程使用。

如果一个字符串包含了字符 ?* 或者 [ 中的一个,那么它就是一个通配符模式。通配符扩展 将一个通配符模式展开为一系列的路径名。匹配是这样定义的:

  • ?: 匹配任意单个字符
  • *: 匹配任何字符串包含空串

字符类

如果由方括号括起来的表达式 [...] 中的第一个字符不是感叹号 !,那么该表达式匹配一个字符。 该字符可以是方括号中的任何一个字符。 方括号内的字串不能为空; 因此 ] 可以位于 方括号中, 但是它必须是第一个字符。 例如,模式:[][!] 匹配三个字符 ][! 之一。

命名字符类

POSIX 定义了以下命名字符类:

[:alnum:]  [:alpha:]  [:blank:]  [:cntrl:]
[:digit:]  [:graph:]  [:lower:]  [:print:]
[:punct:]  [:space:]  [:upper:]  [:xdigit:]

所以,可以使用 [[:lower:]] 代替 [a-z]

范围

有一个特别的规则:由连字符 - 分隔的两个字符代表一个范围。 因此模式 [A-Fa-f0-9] 和 模式 [ABCDEFabcdef0123456789] 等效。如果要想表示连字符本身,可以将它放在方括号的最前面 或者最后面。因此, []-] 匹配字符 ] 或者 -

取反

可以对字符类取反,让字符类匹配除了方括号内的字符以外的任何一个字符。只需要在 开方括号 [ 后面加上一个感叹号 !。例如: [!]a-] 匹配任何一个字符,除了 ]a-

转义

可以通过在字符 '?','*','[' 前面加上反斜杠来去除其特殊含义。然而,当这些特殊字符位于 方括号内部的时候,它们代表自己,没有特殊含义。因此,模式 []?*\] 匹配四个字符:]?*\ 中的一个。

路径名

通配符扩展分别应用于路径名的每个部分。路径名中的 / 不能由 ? 或者 * 匹配,也不能被一个 范围匹配。范围不能显式地包含字符 / ;否则会导致语法错误。

如果一个文件名以 . 开头,该字符必须被显式匹配。因此: rm * 不会删除 .profiletar c * 不会打包所有的文件; 使用 tar c . 是一个更好的选择。

正则表达式

根据 POSIX.2 的定义,有两种格式的正则表达式:扩展正则表达式基本正则表达式。基本 正则表达式当前仍然存在主要是为了保持向后兼容。

定义

扩展正则表达式 是由一个或者多个非空的 branch 由管道符号 | 分隔而成的。只要匹配其中一个 branch 即匹配该正则表达式。

一个 branch 是由一个或者多个 pieces 连接在一起的。

一个 piece 是一个 atom,后跟一个 *+? 或者 bound

一个 atom 可以是:

  • 扩在小括号 () 中的正则表达式
  • 一对空小括号 (),可以匹配空串
  • 一个方括号表达式 [abc...],匹配方括号内的任意一个字符
  • .,英文句点,匹配任何一个字符
  • ^,匹配行首
  • $,匹配行尾
  • 反斜杠后跟以下字符:^.[$()|*+?{\,匹配该字符
  • 反斜杠后跟任何其他字符,匹配那个字符
  • 单个字符,匹配该字符

一个 bound 形如:{start,end},其中:

  • startend 是无符号整数,必须位于 0 和 255(包含)之间
  • ,end 是可选的。
  • 如果有两个整数,第一个不能大于第二个。

如果大括号 { 后跟一个非数字字符,那么大括号就是一个普通字符,不代表 bound 的开始。正则表 达式不能以反斜杠 \ 结尾。

匹配次数

  • 后跟 * 的 atom 匹配该 atom 0 次或者多次
  • 后跟 + 的 atom 匹配该 atom 1 次或者多次
  • 后跟 ? 的 atom 匹配该 atom 0 次或者 1 次
  • 后跟 {start} 的 atom 准确匹配该 atom start 次
  • 后跟 {start,} 的 atom 匹配该 atom start 或者更多次。
  • 后跟 {start,end} 的 atom 匹配该 atom start 到 end(包含)次,包含。

方括号表达式

方括号表达式是括在方括号内的一系列字符。它匹配方括号内的任意一个字符。

  • 要将 ] 放进方括号中,必须将之作为方括号内的第一个字符
  • 要将 - 放进方括号中,必须将之作为方括号内的第一个或者最后一个字符

取反

如果方括号内的字符以 ^ 开头,它匹配任何不在该字符列表中的字符。取反的语法,跟通配符 不同,通配符通过感叹号 ! 在方括号内取反。

范围

在方括号内,可以表示范围。表示范围的语法和通配符相同。如果两个字符以连字符 - 分隔, 那么就代表一个范围。两个范围共享同一端点是非法的,例如:a-c-e。正则表达式的命名字符类和 通配符中使用的命名字符类相同。

基本正则表达式

基本正则表达式有几个方面不一样。

  • | + ? 是普通字符,在基本正则表达式中没有和它们对等的功能。
  • bound 由 \{\} 定义,{} 是普通字符
  • 用于子表达式的小括号是 \(\), () 是普通字符

参考

  • man 7 glob
  • man 7 regex

下一篇 怎么做 Patch

评论