# 简介
本文不会为你介绍所有正则表达式规则,一是我比较懒,二是你记不住。还不如上网去查。
# 定义
关于正则表达式与数据之间的关系,你可以这么理解
数据 --> 正则表达式 --> 匹配的数据
|
v
滤掉的数据
自定义的模式模板 (pattern template), Linux
工具 (sed,gawk) 用来过滤文本。
正则表达式是通过正则表达式引擎 ( regular expression engine
) 实现的,该引擎是一套底层软件,负责解释正则表达式并使用这些模式进行文本匹配。
在 Linux
中,存在两种流行的正则表达式引擎:
POSIX
基础的正则表达式 (basic regular expression,BRE
) 引擎。POSIX
扩展的正则表达式 (extended regular expression,ERE
) 引擎。
大多数 Linux
工具都至少符合 BRE
, 像 sed
等部分工具,出于速度方面的考虑,只能符合 BRE
。 ERE
通常出现依赖正则表达式进行文本过滤的编程语言中,为常见模式提供了高级模式符号和特殊符号。 gawk
程序用 ERE
引擎来处理它的正则表达式模式。
# 定义 BRE 模式
正则表达式并不关心模式在数据流中的位置,也不关心模式出现了多少次,一旦匹配到文本字符串中任意位置上的模式,就会将该字符串传回 Linux
工具,值得注意的是,在正则表达式中,空格和其他字符并没有什么区别。
# 特殊字符
正则表达式存在特殊字符: .*[]^${}\+?|()
。要想在文本中使用这些特殊符号,需要在前加上 \
。
sed -n "/\$/p" data | |
# 尽管正斜线 / 并不是正则表达式中的特殊字符,但是要是出现在 sed 和 gawk 的正则表达式中,也要使用转义 | |
sed -n "/\//p" data |
这些特殊字符具体是什么含义,后面讲解。
# 锚字符
默认情况下,当指定一个正则表达式模式时,只要模式出现在数据流中的任何地方,就能匹配。
- 锁定行首,
^
-- 脱字符,定义从数据流中文本行的行首开始的模式,如果模式出现在行首之外,就无法匹配。
echo "the book store" | sed -n '/^the/p' | |
the book store | |
# 如果是 ^book,就无法匹配 |
- 锁定行尾,使用
$
符号,我记得我在sed
还是gawk
那篇文章讲过。
echo "the book" | sed -n '/book$/p' | |
# 只有以 book 结尾的,才会被匹配 |
# 其他字符
- 点字符
.
,相当于占位符,但是该位置也必须要有字符才行。
echo 'at the' | sed -n '/.at/p' | |
# 匹配失败 |
- 字符组
[]
,该位置如果出现字符组中的任意字符,匹配:echo "to ac" | sed -n '/[ab]c/p'
。可以连续使用多个字符组,但是一个字符组只能占一位。
# 过滤错误的邮政编码(由 5 位数字组成) | |
sed -n ' | |
> /^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p | |
> ' data |
- 排除型字符组,在字符组中开头加上
^
,代表反转,如果该位置没有字符组中的字符,匹配成功。
sed -n '/[^ch]at/p' data |
- 区间,对字符组的优化,比如从
a
到z
不用再挨个列出:[a-z]
, 区间顺序是根据Linux
采用的字符集也可以多次使用,形成不连续的区间并集:[a-ch-m]
, 区间范围为a-c,h-m
。 - 特殊字符组(记不住没关系,我也记不住)
[[:alpha:]] # 匹配任意字母字符,不管是大写还是小写 (alphabet-- 全部字母;字母表) | |
[[:alnum:]] # 匹配任意字母数字字符,0-9,a-z,A-Z | |
[[:blank:]] # 匹配空格和制表符 | |
[[:digit:]] # 匹配 0-9 之间的数字 | |
[[:lower:]] # 匹配 a-z | |
[[:upper:]] # 匹配 A-Z | |
[[:print:]] # 匹配任意可打印字符 | |
[[:punct:]] # 匹配标点符号 | |
[[:sapce:]] # 匹配任意空白字符:空格,制表符,NL,FF,VT,CR |
- 星号,在字符后面放置星号,表明该字符必须在匹配模式的文本中出现 0 次或多次(我觉得这个大家应该都知道吧),
echo 'ik' | sed -n '/ie*k/p
。星号也可以和字符组同时使用,[ac]*
。
# 扩展正则表达式 (ERE)
gawk
程序能够识别 ERE
模式,但是 sed
不能。 gawk
具备这些扩展的功能,但是正因为如此, gawk
程序在处理数据流时通常比较慢。
- 问号
?
,类似于 *, 但是前面的字符只是 0 次或 1 次,也就是,不会匹配多次出现的字符。 - 加号
+
,仍然类似于 *, 但是必须出现 1 次。 - 花括号
{}
,允许为可重复的正则表达式指定一个上限,通常称为间隔 (interval
), 可以用两种格式来指定区间。{m}
:正则表达式准确出现m
次,{m,n}
:正则表达式至少出现m
次,至多出现n
次。对于gawk
来说,默认情况下,gawk
不会识别正则表达式间隔,必须指定gawk
程序的--re- interval
命令行选项才能识别正则表达式间隔。
echo "bt" | gawk --re-interval '/be{1}t/{print $0}' # 匹配失败 | |
echo "bt" | gawk --re-interval '/be{0,1}t/{print $0}' # 匹配成功 |
- 管道符号
|
,符号管道允许在检查数据流时,用逻辑OR
指定正则表达式要用的两个或多个模式,如果任何一个模式匹配了数据流文本,文本通过测试
# expr1|expr2... | |
echo 'the cat is asleep' | gawk '/cat|dog/{print $0}' | |
# 你还记得 lsof 命令的 - a 选项吗 |
- 表达式分组
()
,该组会被视为一个标准字符,可以像对普通字符一样给该组使用特殊字符。
echo "sta" | gawk '/sta(urday)?/{print $0}' # $0 表示整行数据 | |
# 和管道一起使用 | |
echo "cat" | gawk '/(c|b)a(t|d)/{print $0}' |