kwseeker

学编程:找代码,读代码,改代码,写代码;少看书。但少看不是不看,看一本书要限制在一天内。任务是通读书中主要的概念,明白大致是干什么用的,形成一个大概的框架;然后一周内干掉书中全部代码,代码不理解再浏览书中相关章节,注意是浏览。或者刷博客。代码实在刷不懂,可以先刷后面,待日后重新刷;因为书中代码有些部分可能出自后面的章节。代码总是在多次刷过之后,拨开乌云见日月的。。。

导航

正则表达式(转)

  • 正则表达式的用途

  https://msdn.microsoft.com/zh-cn/library/101eysae(v=vs.90).aspx

  通过使用正则表达式,可以:

  1、测试字符串内的模式

    例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。

  2、替换文本

    可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。

  3、基于模式匹配从字符串中提取子字符串

    可以查找文档内或输入域内特定的文本。

  • 正则表达式语法

  https://msdn.microsoft.com/zh-cn/library/ae5bf541(v=vs.90).aspx

  正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”)。模式描述在搜索文本时要匹配的一个或多个字符串。

  下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为:

字符

说明

\

将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,“n”匹配字符“n”。“\n”匹配换行符。序列“\\”匹配“\”,“\(”匹配“(”。

^

匹配输入字符串开始的位置。如果设置了 RegExp对象的 Multiline 属性,^ 还会与“\n”或“\r”之后的位置匹配。

$

匹配输入字符串结尾的位置。如果设置了 RegExp对象的 Multiline 属性,$ 还会与“\n”或“\r”之前的位置匹配。

*

零次或多次匹配前面的字符或子表达式。例如,zo* 匹配“z”和“zoo”。* 等效于 {0,}。

+

一次或多次匹配前面的字符或子表达式。例如,“zo+”与“zo”和“zoo”匹配,但与“z”不匹配。+ 等效于 {1,}。

?

零次或一次匹配前面的字符或子表达式。例如,“do(es)?”匹配“do”或“does”中的“do”。? 等效于 {0,1}。

{n}

是非负整数。正好匹配 n 次。例如,“o{2}”与“Bob”中的“o”不匹配,但与“food”中的两个“o”匹配。

{n,}

是非负整数。至少匹配 次。例如,“o{2,}”不匹配“Bob”中的“o”,而匹配“foooood”中的所有 o。“o{1,}”等效于“o+”。“o{0,}”等效于“o*”。

{n,m}

M 和 n 是非负整数,其中 n <= m。匹配至少 n次,至多 m 次。例如,“o{1,3}”匹配“fooooood”中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。

?

当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是“非贪心的”。“非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的“贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串“oooo”中,“o+?”只匹配单个“o”,而“o+”匹配所有“o”。

.

匹配除“\n”之外的任何单个字符。若要匹配包括“\n”在内的任意字符,请使用诸如“[\s\S]”之类的模式。

(pattern)

匹配 pattern 并捕获该匹配的子表达式。可以使用$0…$9 属性从结果“匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用“\(”或者“\)”。

(?:pattern)

匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用“or”字符 (|) 组合模式部件的情况很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更经济的表达式。

(?=pattern)

执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配“Windows 2000”中的“Windows”,但不匹配“Windows 3.1”中的“Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

(?!pattern)

执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配“Windows 3.1”中的 “Windows”,但不匹配“Windows 2000”中的“Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

x|y

匹配 x 或 y。例如,'z|food' 匹配“z”或“food”。'(z|f)ood' 匹配“zood”或“food”。

[xyz]

字符集。匹配包含的任一字符。例如,“[abc]”匹配“plain”中的“a”。

[^xyz]

反向字符集。匹配未包含的任何字符。例如,“[^abc]”匹配“plain”中的“p”。

[a-z]

字符范围。匹配指定范围内的任何字符。例如,“[a-z]”匹配“a”到“z”范围内的任何小写字母。

[^a-z]

反向范围字符。匹配不在指定的范围内的任何字符。例如,“[^a-z]”匹配任何不在“a”到“z”范围内的任何字符。

\b

匹配一个字边界,即字与空格间的位置。例如,“er\b”匹配“never”中的“er”,但不匹配“verb”中的“er”。

\B

非字边界匹配。“er\B”匹配“verb”中的“er”,但不匹配“never”中的“er”。

\cx

匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是“c”字符本身。

\d

数字字符匹配。等效于 [0-9]。

\D

非数字字符匹配。等效于 [^0-9]。

\f

换页符匹配。等效于 \x0c 和 \cL。

\n

换行符匹配。等效于 \x0a 和 \cJ。

\r

匹配一个回车符。等效于 \x0d 和 \cM。

\s

匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。

\S

匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。

\t

制表符匹配。与 \x09 和 \cI 等效。

\v

垂直制表符匹配。与 \x0b 和 \cK 等效。

\w

匹配任何字类字符,包括下划线。与“[A-Za-z0-9_]”等效。

\W

与任何非单词字符匹配。与“[^A-Za-z0-9_]”等效。

\xn

匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,“\x41”匹配“A”。“\x041”与“\x04”&“1”等效。允许在正则表达式中使用 ASCII 代码。

\num

匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,“(.)\1”匹配两个连续的相同字符。

\n

标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。

\nm

标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 和 m 是八进制数字 (0-7)。

\nml

当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml

\un

匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 生成正则表达式

 https://msdn.microsoft.com/zh-cn/library/6h0s3kc9(v=vs.90).aspx

  正则表达式的结构与算术表达式的结构类似。即,各种元字符和运算符可以将小的表达式组合起来,创建大的表达式。

  分隔符

  通过在一对分隔符之间放置表达式模式的各种组件,就可以构建正则表达式。对于 JScript,分隔符是正斜杠 (/) 字符。例如:

 

   /expression/

 

  在上面的示例中,正则表达式模式 (expression) 存储在 RegExp 对象的 Pattern 属性中。

 

  正则表达式的组件可以是单个字符、字符集、字符的范围、在几个字符之间选择或者所有这些组件的任何组合。

  • 优先级顺序

  下表从最高到最低说明了各种正则表达式运算符的优先级顺序:

运算符

说明

\

转义符

(), (?:), (?=), []

括号和中括号

*, +, ?, {n}, {n,}, {n,m}

限定符

^, $, \任何元字符、任何字符

定位点和序列

|

替换

 

  

 

 

 

 

 

 

 

 

 

字符具有高于替换运算符的优先级,使得“m|food”匹配“m”或“food”。若要匹配“mood”或“food”,请使用括号创建子表达式,从而产生“(m|f)ood”。

  

  • 字符匹配

  https://msdn.microsoft.com/zh-cn/library/901zys3s(v=vs.90).aspx

  句点 (.) 匹配字符串中的各种打印或非打印字符,只有一个字符例外。这个例外就是换行符 (\n)。下面的正则表达式匹配 aac、abc、acc、adc 等等,以及 a1c、a2c、a-c 和 a#c:

 
  /a.c/

  若要匹配包含文件名的字符串,而句点 (.) 是输入字符串的组成部分,请在正则表达式中的句点前面加反斜扛 (\) 字符。举例来说明,下面的正则表达式匹配 filename.ext:

/filename\.ext/

这些表达式只让您匹配“任何”单个字符。可能需要匹配列表中的特定字符组。例如,可能需要查找用数字表示的章节标题(Chapter 1、Chapter 2 等等)。

  中括号表达式
   要创建匹配字符组的一个列表,请在方括号([ 和 ])内放置一个或更多单个字符。当字符括在中括号内时,该列表称为“中括号表达式”。与在任何别的位置一样,普通字符在中括号内表示其本身,即,它在输入文本中匹配一次其本身。大多数特殊字符在中括号表达式内出现时失去它们的意义。不过也有一些例外,如:
  1、如果 ] 字符不是第一项,它结束一个列表。若要匹配列表中的 ] 字符,请将它放在第一位,紧跟在开始 [ 后面。
  2、\ 字符继续作为转义符。若要匹配 \ 字符,请使用 \\。

  括在中括号表达式中的字符只匹配处于正则表达式中该位置的单个字符。以下正则表达式匹配 Chapter 1、Chapter 2、Chapter 3、Chapter 4 和 Chapter 5:

  /Chapter [12345]/

  请注意,单词 Chapter 和后面的空格的位置相对于中括号内的字符是固定的。中括号表达式指定的只是匹配紧跟在单词 Chapter 和空格后面的单个字符位置的字符集。这是第九个字符位置。

  若要使用范围代替字符本身来表示匹配字符组,请使用连字符 (-) 将范围中的开始字符和结束字符分开。单个字符的字符值确定范围内的相对顺序。下面的正则表达式包含范围表达式,该范围表达式等效于上面显示的中括号中的列表。

/Chapter [1-5]/

  当以这种方式指定范围时,开始值和结束值两者都包括在范围内。注意,还有一点很重要,按 Unicode 排序顺序,开始值必须在结束值的前面。

  若要在中括号表达式中包括连字符,请采用下列方法之一:

  1、用反斜扛将它转义:

   
  • [\-]
  2、将连字符放在中括号列表的开始或结尾。下面的表达式匹配所有小写字母和连字符:
  
  • [-a-z]

  • [a-z-]
  • 3、创建一个范围,在该范围中,开始字符值小于连字符,而结束字符值等于或大于连字符。下面的两个正则表达式都满足这一要求:

   [!-~]

  若要查找不在列表或范围内的所有字符,请将插入符号 (^) 放在列表的开头。如果插入字符出现在列表中的其他任何位置,则它匹配其本身。下面的正则表达式匹配编号大于 5 的章节标题:

  /Chapter [^12345]/

  在上面的示例中,表达式在第九个位置匹配 1、2、3、4 或 5 之外的任何数字字符。这样,例如,Chapter 7 就是一个匹配项,Chapter 9 也是一个匹配项。

  上面的表达式可以使用连字符 (-) 来表示:

  /Chapter [^1-5]/

  中括号表达式的典型用途是指定任何大写或小写字母或任何数字的匹配。下面的表达式指定这样的匹配:

  /[A-Za-z0-9]/


深入浅出C/C++中的正则表达式库(一)——GNU Regex Library

原文:http://www.wuzesheng.com/?p=929

写在前面: 本文是面向有正则表达式基础的读者朋友的,如果你还不知道正则表达式是什么,请先到这里学习一下

正则表达式(Regular Expressions),又被称为regex或regexp,是一种十分简便、灵活的文本处理工具。它可以用来精确地找出某文本中匹配某种指定规则的内容。在linux下,grep, sed, awk等工具都支持正则表达式,这些工具的存在,为我们日常的文本处理带来了极大的便利。但是,有时候,我们自己写的程序中也需要用到正则表达式来处理一些文本,这时候就需要一些正则表达式库的支持了。由于我本人是用C/C++做为主要开发语言的,所以,在本文以及接下来的几篇文章中,我将介绍几个常用的C/C++的正则表达式的库,通过我的介绍,以及对具体的使用进行举例,希望能够给读者朋友在C/C++程序中使用正则表达式时有点帮助,这将是我莫大的荣幸。

当前,据我所知,在C/C++中常用的正则表达式库有GNU Regex Library, Boost.Regex, PCRE, PCRE++。这四个库中,后面两个是有关系,其它都是各自己独立的,是不同的实现。因此我会分三次,来一一对这四个库进行介绍。今天首先介绍一下GNU Regex Library。

1. 什么是GNU正则表达式库(GNU Regex Library) ?
GNU正则表达式库是glibc(GNU C Library)的一部分,它提供与POSIX标准兼容的正则表达式匹配的接口。
这里是其主页:http://www.gnu.org/s/libc/manual/html_node/Regular-Expressions.html
下载该库点这里:gnuregex0_13 

2. GNU Regex Library所提供的接口
(1)regcomp:

1
2
3
4
5
6
int regcomp(regex_t *preg, const char *pattern, int cflags)
功能:将要进行匹配的正则表达式pattern进行编译,做匹配前的准备工作
参数: preg, 输出参数,用来保存编译后的正则表达式结果
      pattern, 输入参数,传入要进行编译的正则表达式的字符串
      cflags, 输入参数,用来指定正则表达式匹配过程中的一些选项
返回值:编译成功返回0,失败返回非0的错误码

 

 

 

 

(2)regexec:

1
2
3
4
5
6
7
8
9
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], 
            int eflags)
功能:用来检测字符串string是否匹配正则表达式preg
参数: preg, 输入参数,在(1)regcomp中编译好的正则表达式规则
      string, 输入参数,用来被匹配的字符串
      nmatch, 输入参数,用来指定pmatch参数所对应的数组的长度
      pmatch, 输出参数,用来输出在string中匹配preg的具体位置
      eflag, 输入参数,用来指定正则表达式匹配过程中的一些选项
返回值: 如果string匹配preg所指定的规则,则返回0, 否则返回非0

 

 

 

 

 

 

(3)regerror:

1
2
3
4
5
6
7
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
功能:用来把在regcompt和regexec中产生的错误码转化成字符串形式的错误信息
参数: errcode, 输入参数,在regcomp或regexec调用中返回的错误码
      preg, 输入参数,与错误码所对应的编译过的正则表达式结构
      errbuf, 输出参数,用来返回错误信息的buffer,如果buffer不够所需大小,错误信息将被截断
      errbuf_size, 输入参数,返回错误信息的buffer的大小 
返回值: 如果errbuf_size为0,那么regerror返回错误信息所需要的buffer的大小

 

 

 

 

 

(4)regfree:

1
2
3
4
void regfree (regex_t *preg)
功能: 用来释放由regcomp编译时生成的preg结构所占用的内存
参数: preg, 输入参数,由regcomp编译时生成的正则表达的结构指针
返回值: 无

 

 

 

3. 使用GNU Regex Library的一些注意事项
(1)regcomp与regfree必须配对使用,要不然会造成内存泄漏(类比malloc/free, new/delete)
(2)regex_t结构:把字符串形式的正则表达式编译成regex_t这样的一个结构,方便后续的匹配工作
(3)regmatch_t结构:用来表示正则表达式中字符串中匹配的位置的结构,用起始位置的偏移量来表示的
(4)flags:用来配置匹配过程中的一些选项, 指定如何匹配,具体参见:http://www.opengroup.org/onlinepubs/007908799/xsh/regcomp.html
(5)使用该库需要包含的头文件:sys/types.h和regex .h

4. GNU Regex Library使用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <sys /types.h>
#include <regex .h>
#include <stdio .h>
 
int main(int argc, char ** argv)
{
    if (argc != 3)
    {
        printf("Usage: %s RegexString Text\n", argv[0]);
        return 1;
    }
 
    const char * pRegexStr = argv[1];
    const char * pText = argv[2];
 
    regex_t oRegex;
    int nErrCode = 0;
    char szErrMsg[1024] = {0};
    size_t unErrMsgLen = 0;
 
    if ((nErrCode = regcomp(&oRegex, pRegexStr, 0)) == 0)
    {
        if ((nErrCode = regexec(&oRegex, pText, 0, NULL, 0)) == 0)
        {
            printf("%s matches %s\n", pText, pRegexStr);
            regfree(&oRegex);
            return 0;
        }
    }
 
    unErrMsgLen = regerror(nErrCode, &oRegex, szErrMsg, sizeof(szErrMsg));
    unErrMsgLen = unErrMsgLen < sizeof(szErrMsg) ? unErrMsgLen : sizeof(szErrMsg) - 1;
    szErrMsg[unErrMsgLen] = '\0';
    printf("ErrMsg: %s\n", szErrMsg);
 
    regfree(&oRegex);
    return 1;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

程序测试:

1
2
3
4
5
wuzesheng@wuzesheng-ubuntu:~/Program$ gcc TestRegex.c -o Regex
wuzesheng@wuzesheng-ubuntu:~/Program$ ./Regex "http:\/\/www\..*\.com" "https://www.taobao.com"
ErrMsg: No match
wuzesheng@wuzesheng-ubuntu:~/Program$ ./Regex "http:\/\/www\..*\.com" "http://www.taobao.com"
http://www.taobao.com matches http:\/\/www\..*\.com

 

 

 

 

以上即是关于GNU Regex Library的全部内容。如果读书者朋友有什么看法可以在下面给我留言。接下来几天,我会陆续介绍前面提到的其它几个库,今天先到这里。

 

作者关于另两种库进行正则表达式匹配文章:

深入浅出C/C++中的正则表达式库(二)——Boost.Regex      http://www.wuzesheng.com/?p=965

 深入浅出C/C++中的正则表达式库(三)——PCRE, PCRE++ http://www.wuzesheng.com/?p=994

  

posted on 2015-09-27 19:35  kwseeker  阅读(372)  评论(0编辑  收藏  举报