正则表达式是一种字符串匹配模式, Linux 工具可以用它来过滤文本
正则表达式引擎
正则表达式引擎是一套底层软件, 负责解释正则表达式以及使用它来匹配文本, 正则表达式是通过正则表达式引擎实现的
以下是两种 Linux 流行的正则表达式引擎
- POSIX 基础正则表达式(BRE)引擎
- POSIX 扩展正则表达式(ERE)引擎
大多数 Linux 工具至少符合 POSIX BRE 引擎规范, sed 编辑器仅部分支持 BRE 引擎, gawk 程序则支持 ERE 引擎
基本正则表达式
纯文本
打印多行文本
echo -e "A\nB\nC"
A
B
C
-e 选项启用转义效果, “\n” 被解释为换行符
sed 编辑器
echo -e "AA\nBC\nBD" | sed -n '/B/p'
BC
BD
sed 的 -n 选项禁止正常输出, 带模式匹配的 p 命令仅打印包含 B 的文本行
gawk 程序脚本
echo -e "AA\nBC\nBD" | gawk '/B/{print $0}'
BC
BD
gawk 程序脚本中 $0 表示整个文本行, 当该行包含 B 时才打印
grep 文本搜索
echo -e "AA\nBC\nBD" | grep B
BC
BD
grep 搜索包含 B 的文本行
这三个工具的共同点: 对文本中的每一行进行匹配
特殊字符
特殊字符包括 .*[]^${}\+?|()
当特殊字符出现在正则表达式里时, 必须使用 \ 进行转义
echo '$$' | sed -n '/\$/p'
$$
在 shell 中 $$ 表示当前进程 PID(下图演示了这个用法), 但这里 echo '$$'
使用了单引号, 仅表示两个美元符
锚字符
行首
^ 表示从行首开始匹配
echo -e "AB\nBC\nCD" | sed -n '/^B/p'
BC
打印以 B 开头的行
行尾
$ 表示以行尾结束匹配
echo -e "AB\nBC\nCD" | sed -n '/C$/p'
BC
打印以 C 结尾的行
组合
echo -e "AB\nBC\nCD" | sed -n '/^BC$/p'
BC
以 B 开头且以 C 结尾
^$ 中间不加任何字符表示匹配空行(行首与行尾之间什么都没有)
echo -e "A\n\nB" | sed '/^$/d'
A
B
sed 的 d 命令表示删除文本行, 该示例匹配空行并删除
点号字符
. 表示除换行符外的任意一个字符
echo -e "A\nAB\nABC" | sed -n '/A./p'
AB
ABC
AB 和 ABC 都能匹配 A. 模式
字符集
使用方括号包裹一组字符, 只要其中的一个字符被匹配了即视为匹配
echo -e "A\nAB\nAC\nAD" | sed -n '/A[BC]/p'
AB
AC
反向匹配
[^ABC] 表示匹配除 A, B, C 以外的任意单个字符
echo -e "A\nAB\nAC\nAD" | sed -n '/A[^BC]/p'
AD
使用区间
指定单个区间
echo -e "A0\nA1\nA2\nA3\nAB" | sed -n '/A[0-2]/p'
A0
A1
A2
指定多个区间
echo -e "AB\nAC\nAD\nAE\nAF" | sed -n '/A[A-BE-F]/p'
AB
AE
AF
字符与区间并存
echo -e "AB\nAC\nAD\nAE\nAF" | sed -n '/A[A-BE-FC]/p'
AB
AC
AE
AF
反向匹配模式
echo -e "AB\nAC\nAD\nAE\nAF" | sed -n '/A[^B-CF]/p'
AD
AE
特殊字符组
组 | 范围 |
---|---|
[[:alpha:]] | 任意字母 a-z 或 A-Z |
[[:alnum:]] | 任意字母或数字 a-z, A-Z 或 0-9 |
[[:digit:]] | 数字 0-9 |
[[:lower:]] | 小写字母 a-z |
[[:upper:]] | 大写字母 A-Z |
echo -e "A\nAB\nABC\nAC" | sed -n '/A[[:alpha:]]/p'
AB
ABC
AC
可以在特殊字符组里添加自己的内容
echo -e "A\nA1\nAB\nAC" | sed -n '/A[[:alpha:]1]/p'
A1
AB
AC
星号
* 表示匹配字符可以出现 0 次或多次
echo -e "AT\nABT\nACT\nABBT\nABBBT" | sed -n '/AB*T/p'
AT
ABT
ABBT
ABBBT
在 A 与 T 之间, B 出现的次数任意
echo -e "AT\nABT\nABCT\nACBCT" | sed -n '/A[BC]*T/p'
AT
ABT
ABCT
ACBCT
在 A 与 T 之间, B 与 C 以任意形式组合均能被匹配
扩展正则表达式
grep 搜索的升级版本 egrep 和 gawk 程序均支持扩展正则匹配
问号
? 表示匹配字符可以出现 0 次或 1 次
echo -e "AT\nABT\nACT\nABBT" | egrep 'AB?T'
AT
ABT
A 与 T 之间的 B 可出现 0 次或 1 次
加号
+ 表示匹配字符至少出现 1 次
echo -e "AT\nABT\nACT\nABBT" | egrep 'AB+T'
ABT
ABBT
A 与 T 之间的 B 至少出现 1 次
花括号
有两种形式:
-
{m} 表示前面的字符重复出现 m 次
-
{m, n} 表示前面的字符重出现 m-n 次, m 和 n 可以省略其一
- {m,} 至少重复 m 次
- {,n} 至多重复 n 次
echo -e "AT\nABT\nACT\nABBT\nABBBT" | egrep 'AB{2}T'
ABBT
A 与 T 之间的 B 重复出现 2 次
echo -e "AT\nABT\nACT\nABBT\nABBBT" | egrep 'AB{0,2}T'
AT
ABT
ABBT
A 与 T 之间的 B 重复出现 0 - 2 次
echo -e "AT\nABT\nACT\nABBT\nABBBT" | egrep 'AB{2,}T'
ABBT
ABBBT
A 与 T 之间的 B 至少重复出现 2 次
echo -e "AT\nABT\nACT\nABBT\nABBBT" | egrep 'AB{,2}T'
AT
ABT
ABBT
A 与 T 之间的 B 至多重复出现 2 次
管道
允许使用逻辑或的方式指定多个正则匹配模式, 只要其中一个模式匹配了文本, 则匹配成功
echo -e "Cat\nDog\nFish" | egrep 'Cat|Dog'
Cat
Dog
分组
一个组可以包含多个字符, 在匹配时这些字符视为一个标准字符
echo -e "A\nABC\nACB\nABCBC" | egrep "A(BC)+"
ABC
ABCBC
“BC” 这一组字符至少重复出现 1 次