2024年3月20日发(作者:)
Linux/Unix工具与正则表达式的POSIX规范
内容来源于 更多内容请查看网站
对正则表达式有基本了解的读者,一定不会陌生『d』、『[a-z]+』之类的表达式,前者
匹配一个数字字符,后者匹配一个以上的小写英文字母。但是如果你用过vi、grep、awk、
sed之类Linux/Unix下的工具或许会发现,这些工具虽然支持正则表达式,语法却很不一样,
照通常习惯的办法写的『d』、『[a-z]+』之类的正则表达式,往往不是无法识别就是匹配错
误。而且,这些工具自身之间也存在差异,同样的结构,有时需要转义有时不需要转义。这,
究竟是为什么呢?
原因在于,Unix/Linux下的工具大多采用POSIX规范,同时,POSIX规范又可分为两
种流派(flavor)。所以,首先有必要了解一下POSIX规范。
POSIX规范
常见的正则表达式记法,其实都源于Perl,实际上,正则表达式从Perl衍生出一个显赫
的流派,叫做PCRE(Perl Compatible Regular Expression),『d』、『w』、『s』之类的记法,
就是这个流派的特征。但是在PCRE之外,正则表达式还有其它流派,比如下面要介绍的
POSIX规范的正则表达式。
POSIX的全称是Portable Operating System Interface for uniX,它由一系列规范构成,定
义了UNIX操作系统应当支持的功能,所以“POSIX规范的正则表达式”其实只是“关于正则
表达式的POSIX规范”,它定义了BRE(Basic Regular Expression,基本型正则表达式)和
ERE(Extended Regular Express,扩展型正则表达式)两大流派。在兼容POSIX的UNIX系
统上,grep和egrep之类的工具都遵循POSIX规范,一些数据库系统中的正则表达式也符
合POSIX规范。
BRE
在Linux/Unix常用工具中,grep、vi、sed都属于BRE这一派,它的语法看起来比较奇
怪,元字符『(』、『)』、『{』、『}』必须转义之后才具有特殊含义,所以正则表达式『(a)b』
只能匹配字符串 (a)b而不是字符串ab;正则表达式『a{1,2}』只能匹配字符串a{1,2},正
则表达式『a{1,2}』才能匹配字符串a或者aa。
之所以这么麻烦,是因为这些工具的诞生时间很早,正则表达式的许多功能却是逐步发
展演化出来的,之前这些元字符可能并没有特殊的含义;为保证向后兼容,就只能使用转义。
而且有些功能甚至根本就不支持,比如BRE就不支持『+』和『?』量词,也不支持多选结
构『(…|…)』和反向引用『1』、『2』…。
不过今天,纯粹的BRE已经很少见了,毕竟大家已经认为正则表达式“理所应当”支持
多选结构和反向引用等功能,没有确实太不方便。所以虽然vi属于BRE流派,但提供了这
些功能。GNU也对BRE做了扩展,支持『+』、『?』、『|』,只是使用时必须写成『+』、『?』、
『|』,而且也支持『1』、『2』之类反向引用。这样,GNU的grep等工具虽然名义上属于
BRE流,但更确切的名称是GNU BRE。
ERE
在Linux/Unix常用工具中,egrep、awk则属于ERE这一派,。虽然BRE名为“基本”而
ERE名为“扩展”,但ERE并不要求兼容BRE的语法,而是自成一体。因此其中的元字符不
用转义(在元字符之前添加反斜线会取消其特殊含义),所以『(ab|cd)』就可以匹配字符串
ab或者cd,量词『+』、『?』、『{n,m}』可以直接使用。ERE并没有明确规定支持反向引用,
但是不少工具都支持『1』、『2』之类的反向引用。
GNU出品的egrep等工具就属于ERE流(更准确的名字是GNU ERE),但因为GNU
已经对BRE做了不少扩展,所谓的GNU ERE其实只是个说法而已,它有的功能GNU BRE
都有了,只是元字符不需要转义而已。
下面的表格简要说明了几种POSIX流派的区别(其实,现在的BRE和ERE在功能上
并没有什么区别,主要的差异是在元字符的转义上)。
几种POSIX流派的说明
流派
BRE
说明
(、)、{、}都必须转义使用,不支持
+、?、|
工具
grep、sed、vi(但vi支
持这些多选结构和反向引
用)
GNU grep、GNU sed
egrep、awk
GNU BRE
ERE
(、)、{、}、+、?、|都必须转义使用
元字符不必转义,+、?、(、)、{、}、
|可以直接使用,1、2的支持不确定
元字符不必转义,+、?、(、)、{、}、
|可以直接使用,支持1、2
GNU ERE
grep –E、GNU awk
为了方便查阅,下面再用一张表格列出基本的正则功能在常用工具中的表示法,其中的
工具GNU的版本为准。
常用Linux/Unix工具中的表示法
PCRE记法
*
+
?
{m,n}
vi/vim
*
+
=
{m,n}
grep
*
+
?
{m,n}
awk
*
+
?
{m,n}
sed
*
+
?
{m,n}


发布评论