# 简介

本文不会为你介绍所有正则表达式规则,一是我比较懒,二是你记不住。还不如上网去查。

# 定义

关于正则表达式与数据之间的关系,你可以这么理解

数据 --> 正则表达式 --> 匹配的数据
            |
            v
        滤掉的数据

自定义的模式模板 (pattern template), Linux 工具 (sed,gawk) 用来过滤文本。

正则表达式是通过正则表达式引擎 ( regular expression engine ) 实现的,该引擎是一套底层软件,负责解释正则表达式并使用这些模式进行文本匹配

Linux 中,存在两种流行的正则表达式引擎:

  • POSIX 基础的正则表达式 ( basic regular expression,BRE ) 引擎。
  • POSIX 扩展的正则表达式 ( extended regular expression,ERE ) 引擎。

大多数 Linux 工具都至少符合 BRE , 像 sed 等部分工具,出于速度方面的考虑,只能符合 BREERE 通常出现依赖正则表达式进行文本过滤的编程语言中,为常见模式提供了高级模式符号和特殊符号。 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
  • 区间,对字符组的优化,比如从 az 不用再挨个列出: [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}'