正则表达式通常简称 regex,用于描述文本模式。grep、sed 和 awk 等工具都会使用正则表达式,但它们支持的语法可能不同,因此务必先确定所用工具和正则表达式风格。
GNU grep 默认使用基本正则表达式(BRE),加上 -E 后使用扩展正则表达式(ERE)。本课先介绍两者共有的结构,再说明常见的 ERE 扩展。
高级文本操作 · 第 1 课
学习锚点、字符集合、重复规则和正则表达式风格如何控制文本模式匹配。
正则表达式通常简称 regex,用于描述文本模式。grep、sed 和 awk 等工具都会使用正则表达式,但它们支持的语法可能不同,因此务必先确定所用工具和正则表达式风格。
GNU grep 默认使用基本正则表达式(BRE),加上 -E 后使用扩展正则表达式(ERE)。本课先介绍两者共有的结构,再说明常见的 ERE 扩展。
以下示例使用这段输入:
sally sells seashells
by the seashore
大多数普通字符会匹配自身。模式 seashells 会选择任何位置包含这一确切字符序列的行:
$ grep 'seashells' sample.txt
sally sells seashells
请为正则表达式模式加引号,避免 shell 在匹配工具收到它们之前进行展开或拆分。正则表达式也不同于 shell 路径名展开:在正则表达式中,* 重复它前面的原子;在 shell glob 中,* 本身就是匹配一串路径名字符的通配符。
在 ab* 这样的正则表达式中,* 有什么作用?
在方括号表达式之外,模式开头的 ^ 会把匹配锚定在行首:
^by
$ 锚点匹配行尾:
seashore$
如果整行都必须符合模式,请组合两个锚点:
^by the seashore$
哪个模式只匹配完整文本为 by the seashore 的行?
在普通的面向行正则表达式模式中,点号会匹配一个字符:
b.
它能匹配 by,也可能匹配 ba 或 b7。它不能匹配单独的 b,因为后面必须还有一个字符。若要匹配字面句点,请写成 \.,或把它放入适当的方括号表达式。
以下哪个字符串不会被完整行模式 ^b.$ 匹配?
方括号表达式会从指定集合中匹配一个字符:
s[ae]lls
它可以在相应位置匹配 sells 或 salls。
当 ^ 是 [ 后面的第一个字符时,它会对集合取反:
s[^e]lls
它会匹配 salls,但不会匹配 sells,因为第一个 s 后面的字符不能是 e。
[^e] 会匹配什么?
范围可以描述两个端点之间的字符:
d[a-c]g
它可以匹配 dag、dbg 或 dcg。范围行为可能受 locale 排序规则影响。[[:lower:]]、[[:upper:]] 和 [[:digit:]] 等字符类通常能更清楚地表达意图。
在 BRE 和 ERE 中,* 都表示前一个原子重复零次或多次:
seashells*
它会匹配 seashell 后跟零个或多个额外的 s。在使用 grep -E 的 ERE 模式下,常见运算符包括:
+:重复一次或多次。?:重复零次或一次。|:匹配左侧或右侧表达式。(...):对表达式分组。例如:
$ grep -E '^(cat|dog)s?$' animals.txt
它会选择完整内容等于 cat、cats、dog 或 dogs 的行。在 BRE 模式中,这些运算符的转义规则不同,因此不要在未检查的情况下跨风格复制模式。
哪个命令会为模式 ^(cat|dog)s?$ 启用扩展正则表达式语法?
要练习使用 Linux 文本工具进行正则选择,可以尝试以下动手实验:
grep 搜索 Linux 文件中的文本,包括基本搜索、显示行号、使用 ^ 和 $ 锚点,以及运用基本和扩展正则表达式进行复杂模式匹配。课程已完成
现在,你可以阅读和构建基础的面向行正则表达式。
区分正则表达式运算符和 shell 路径名通配符。
把匹配锚定在行首或行尾。
使用点号或方括号表达式匹配一个字符。
对集合取反,并使用 locale 相关的字符类。
有意识地选择 BRE 或 ERE 语法。