正则表达式(regexps),是一种概念,简单来说就是一组对正在查找的文本的描述。目前在GNU/Linux 中有两套可用于正则表达式编成的库:POSIX 库和PCRE库。前者是Linux自带的正则表达式库,后者是Perl的正则表达式库。从功能上看PCRE风格的正则表达式更强大。但本文章,就POSIX库来讨论。
字符集和单词
“.” 用于匹配除了换行符以外的任一个字符。例如 以下的表达式匹配 cat、bat等字符。
.at
“.”能够匹配的范围很大。上面的表达式也可以匹配 ~at、#at等。
“[]”方括号用于指定一个字符集。无论”[]”里面有多少字符,都匹配其中的一个。比如下面的表达式匹配a或者b或者c,但是不能匹配ad、ac、bc等:
[abc]
还可以使用“-”连字符来描述一个范围。下面的表达式匹配所有的英文字母。
[a-zA-Z]
下面的表达式用于表示数字
[0-9]
正则中的单词的含义,指的是两侧有非单词字符分隔开的字符串。非单词字符指的是字母、数字、下划线以外的任何字符。
“\<”和“>”为分割符号,可以表示分隔的单词。例如:
'\<[a-z]at\>'
表示了bat等单词的匹配,同样的,正则中对单词的定义可以知道,a#%bat、bat!!! 这样的单词也被匹配了。因为 “a#%bat”分别有标点$和行尾分隔,符合单词的定义。abat 就不会被匹配,因为bat之前的有单词字符 a。
位置匹配
“^”和“$”分别用于匹配行首和行尾。下面这条正则匹配了所有以a开头,t结尾、a和t之间包含一个小写字母的行:
^a[a-z]t$
他们两个不需要一定同时使用:
^[0-9]
所有以数字开头的行
字符类
除了字符集,POSIC风格的正则表达式还提供了预定字符类,例如下面的表达式,匹配了所有以大写字母开头,以小写字母结尾的行:
^[[:upper:]]t$
正则[[:upper:]] 就是一个字符类,表示所有大写字母,等价于[A-Z]。下表列出了完整的字符类表示。
类 | 匹配字符 |
---|---|
[[:alnum:]] | 文字、数字字符 |
[[:alpha:]] | 字母字符 |
[[:lower:]] | 小写字母 |
[[:upper:]] | 大写字母 |
[[:digit:]] | 数字 |
[[:xdigit:]] | 十六进制数字 |
[[:punct:]] | 标点符号 |
[[:blank:]] | 制表符和空格 |
[[:space:]] | 空格 |
[[:cntrl:]] | 所有控制符 |
[[:print:]] | 所有可打印的字符 |
[[:graph:]] | 除空格外所有可打印的字符 |
字符转义
和编程语言中的转义基本一致,为了匹配字符本省,就需要yoga到转义。例如 “.”之前提到可以在正则中匹配任意一个字符,但是需要匹配字符“.”,就要用转义了。表示为“.”。
“\”本身的转义用”\\”表示。
重复
用于重复的字符有下面这些符号:
元字类 | 描述 |
---|---|
* | 重复次数 >= 0 |
+ | 重复次数 >= 1 |
? | 0<=重复次数 <=1 |
{n} | 重复次数 = n |
{n,} | 重复次数 >= n |
{n,m} | n<=重复次数 <= m |
例如,下面的表达式匹配以a开头、以t结尾的行
^a.*t$
其中,^a表示以a开头的;“.”表示匹配一个字符(除了换行符);“*”表示之前的那个字符可以重复0次或者更多次;“t$”表示以t结尾。
子表达式
字表达是表示分组。例如:
(or){2,}
他表示匹配所有 or重复2次或者更多次的行。如果去掉(or)两边的括号,那么正则表达式匹配的是o后面紧跟着两个或者更多个字母r的行。
反义
表示 除了这个字符以外的其他字符 这类的表达方式。例如 匹配除了字母y以外的任何字符
[^y]
注意“^”和在行首的区别。
分支
正则表达式对用户提交的信息简单地执行“与”的组合。例如,以字母h开头 并且 以字母t结尾的行:
^ht$
如果要表示 或者的概念,需要通过 | 来表示,例如 ,以字母h开头或者 以t结尾的行:
^h|t$
再看一个例子:
Jan(uary| |\.)
将匹配January、 Jan 或者Jan. 这样的字符串。
逆向引用
在子表达式(分组) 中捕获的内容可以在正则表达式中的其他地方再次使用,用于可以使用反斜杠 “\”加上子表达式的编号来指代该分组的内容。例如:
(\<.*\>).?()&\1
上面这个表达式 匹配了 在某个单词出现后,紧跟着0个或者1个标点符号,以及任意个空格之后再次出现这个单词的行。例如:cart cart、long ,long、haha!haha这类。
- (\<.*>) 匹配任意长度的单词。
- .? 匹配0个或者1个标点符号。由于 . 之前匹配的是单词 ,所有 .匹配的只剩下了标点符号了。
- ( )* 匹配任意个空格
- \1 指代第一个子表达式匹配到的模式。第一个匹配到的是cart ,这个匹配到的也是cart