正则表达式定义
正则表达式 (regular expression) 是 Linux 系统中一种非常重要的字符串搜索模式,是一组规则字符的集合。这些规则字符能够组成我们所需要的搜索规则,效率高、功 能强,可以极大地简化处理字符串时的复杂度。在很多 Linux 工具 (sed 、 grep 、 find 等 ) 和脚本语言 (awk 、 perl 等 ) 中都有着重要的地 位。当我们在编写字符串相关的应用程序时,掌握正则表达式会起到事半功倍的效果。
C 中的正则表达式
标准 C 和 C++ 都不支持正则表达式,但是千万不要以为正则表达式就只是 Perl 、 Python 、 Bash 等脚本语言的专利,作为 C 语言程序员,用户同样可 以在自己的程序中运用正则表达式,只是需要一些函数库辅助 C/C++ 程序员来完成这一功能。许多 Linux 发行版本都带有 POSIX 函数库,下面我将以 POSIX 函数库中的 Regex 系列函数来说明在 Linux c 下如何使用正则表达式。
首先要用 Regcomp() 函数对它进行编译,将其转化为 Regex_t 结构。因为一个正则表达式需要编译成一个特定的数据结构才能被后续的函数使用。 Regcomp() 函数的原型是:
int Regcomp(regex_t *preg, const char *regex, int cflags)
参数 preg 指向一个声明为 regex_t 的数据结构,用来保存编译结果。参数 regex 为要编译的正则表达式字符串。参数 cflags 是编译开关,编译 开关可以控制规则生成的特性,如 REG_EXTEND 代表使用扩展正则表达式模式; REG_ICASE 表示对规则中字符串不区分大小 写; REG_NOSUB 只检查是否有符合规则的子串。
下面匹配正则表达式,一旦用 Regcomp() 函数成功地编译了正则表达式,接下来就可调用 regexec() 函数完成模式匹配。 Regexec() 函数的原型:
int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags)
函数用于在字符串 ( 参数 string) 中匹配正则表达式 ( 参数 preg) 。而参数 nmatch 和 pmatch 则用于把匹配结果返回给调用程序。在调用函数 egexec() 进行模式匹配的过程中,可能在字符串 string 中会有多处与给定的正则表达式相匹配。参数 pmatch 用来保存这些匹配位置。参数 nmatch 则告诉函数 regexec() 最多可以把多少个匹配结果填充到 pmatch 数组中。
typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;
其中 rm_so 表示满足规则的子串在 string 中的起始偏移量, rm_eo 表示满足规则的子串在 string 中的后续偏移量。当 regexec 成功返回 时,从 pmatch[0].rm_so 到 pmatch[0].rm_eo 是第一个匹配的字符串。最后一个参数 eflags 决定了匹配的特性,当需要匹配的 string 非常大的时候可以通过 eflags 来表示是否是第一行 (REG_NOTBOL) ,或最后一行 (REG_NOTEOL) 。
还有一个函数是用来获取错误信息的, size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) 。参数 errcode 是来自函数 Regcomp() 或 regexec() 的错误代码,而参数 preg 则是由函数 Regcomp() 得到的编译结果,其目的是把格式化消息所必须的上下文提供给 regerror() 函数。在执行函数 regerror() 时,将按照参数 errbuf_size 指明的最大字节数。在 errbuf 缓冲区中填入格式化后的错误信息,同时返回错误信息的长度。
最后释放正则表达式。无论什么时候,当不再需要已经编译过的正则表达式时,都应该调用函数 regfree() 将其释放,以免产生内存泄漏。 void regfree(regex_t *preg); 函数 regfree() 不会返回任何结果,它仅接收一个指向 regex_t 数据类型的指针,这是之前调用 Regcomp() 函数所得到的编译结果。
正则表达式示例表
字 符 意 义 示 例
* 任意长度的字符串。 a* 表示 : 空字符串、 aaaa 、 a…
? 长度为 0 或者 1 的字符串。 a? 表示 : 空字符串和 a 。
+ 长度为一个或者多个的字符串。 a+ 表示 :a 、 aa 、 aaaaaa…
. 任意字符。 a. 表示 :a 后跟任意字符。
{} 代表上一规则重复数目、
{1,1,s} 包含一组匹配花括号,里面有两个数字和一个字符,表示在指定次数范围内找到字符。 a{3} 表示 : 三个 a 、
a{1,3} 表示 : 一个到三个 a 、
a{3,} 表示 : 大于等于三个 a 、
{3 , 7 , a} 表示在 3 到 7 次重复范围内匹配字符 a 。
[] 集合 , 代表方括号中任意一个字符。 [ab] 表示 :a 或者 b 都可以、
[a-z] 表示 : 从 a 到 z 的字符。
() 组 , 代表一组字符。 (ab){2} 表示 :abab 。
a/b 同时满足。 a/b 表示 : 字符串 a 后跟字符串 b 才能满足要求。
a|b 并列 , 代表符合 a 或者符合 b 都可以 a|b 表示 : 字符串 a 或者字符串 b 都满足要求。
^ 如果放在开头表示代表该规则必须在字符串的开头,其他位置代表字符本身。
如果放在 [] 中的开头表示对该集合取反 , 其他位置代表字符本身。 ^a 表示 :a 必须在字符串的开头、
[^a] 表示 : 除了 a 以外的其他字符。
$ 如果放在最后表示该规则必须放在最后 , 其他位置代表字符本身。 a$ 表示 :a 必须在字符串最后。
/:s 正则表达式用 /:s 表示空格。 a/:sb 匹配 a b 。
/:a 正则表达式用 /:a 表示字符与数字。 a/:a 匹配 ab 、 a6 等。
/:c 正则表达式用 /:c 仅表示字符。 a/:c 匹配 ac 等,不匹配 a1 等。
/:p 正则表达式用 /:p 表示可打印字符。
/:D 正则表达式用 /:d 仅表示数字。 a/:c 匹配 a1 等,不匹配 ac 等。
/:x00 正则表达式用 /:x00 表示 ASCII 字符。
/:r 正则表达式用 /:r 表示回车。
/:N 正则表达式用 /:d 表示换行。
具体请:man regex