正则表达式使用技巧整理

测试工具

https://c.runoob.com/front-end/854

常用技巧

S: 	表示匹配任何非空白字符。等价于 [^ f

	v]。
s: 	表示匹配匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ f

	v]。
[sS]:表示出现空白和非空白中的任意一个字符,即是任意字符
w: 	匹配字母或数字或下划线或汉字 等价于 ‘[A-Za-z0-9_]’。 
s :	匹配任意的空白符 
d :	匹配数字 
 :	匹配单词的开始或结束 
*: 	匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 *。
+:  	匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。
|:	指明两项之间的一个选择。要匹配 |,请使用 |。
^:	匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字	符集合。要匹配 ^ 字符本身,请使用 ^。
{n,m} 	表示n 到m 次

典型例子

正则表达式匹配双引号之间的数据 但不包括双引号

"([^"]*)"
样本:
abcs"fdsdfs" ffd fs "fwert423wr" "fsd fsf,ewrer"
匹配结果:
"fdsdfs"  "fwert wtewr"  "fsd fsf,ewrer"

分割字符串但是不分割字符串中引号中间的数据

(?<!"[^,]+),(?![^,]+")     (C#)Regex.Split
(w|.)+[^,]|"[^"]*"|w  (c++)
样本:11211,210161,"SHRINK FILM, 23 W X .0015MIL",49.95,RM1 ,1
匹配结果:11211  210161  "SHRINK FILM, 23 W X .0015MIL"  49.95  RM1  1

按空格分隔 但不分隔引号中的空格

w+:(w+|"[^"]*")+?
样本:name:Lily age:23 class:"class 1"
匹配结果:name:Lily    age:23    class:"class 1"

另一小例---局部批对字符串

上海?[^,。、s]+公司
样本: 	1	上海汽车集团股份有限公司	51	上海春秋国际旅行社(集团)有限公司
		 2	交通银行股份有限公司	52	上海斐讯数据通信技术有限公司
		 3	上海浦东发展银行股份有限公司	53	康德乐医药有限公司
		 4	中国太平洋保险(集团)股份有限公司	54	上海机场(集团)有限公司
匹配结果:
上海汽车集团股份有限公司
上海春秋国际旅行社(集团)有限公司
上海斐讯数据通信技术有限公司
上海浦东发展银行股份有限公司
上海机场(集团)有限公司

获取以-成对的字符串

w+s*-(s*[^,;]+)
样本:
fsd-fsdfs fds-fsdfs,werfsd-fewrwrw;fewrwer,fdf  -fdf fsdew- fd90
匹配结果:
fsd-fsdfs
fds-fsdfs
werfsd-fewrwrw
fdf  -fdf
fsdew- fd90

另一小例

[^,"]+|,,|(?:"[^,"]*"[^"]*"[^"]*)"|"(?:[^"])*"
样本: your dollors,10000, 27 years old ,,"10,000","it is "10 Grand",baby",10k
匹配结果: your dollors 10000  27 years old  ,,   "10,000"   "it is "10 Grand",baby"   10k

C++ 代码 获取匹配的字符串数组或替换

#include <regex>
#include <string>
   // 使用类 std::regex_iterator 来进行多次搜索.
    static std::string _strs = "... ..." ; 
    std::regex _regex("<img [^>]+>");
    std::cout << "sregex_iterator ====" << std::endl;
    auto words_begin =
        std::sregex_iterator(_strs.begin(), _strs.end(), _regex);
    auto words_end = std::sregex_iterator();
    for (std::sregex_iterator i = words_begin; i != words_end; ++i)
    {
        std::smatch match = *i;                                                 
        std::string match_str = match.str();
        std::cout << match_str << '
';
}

// 把所有 img src 的绝对路径替换为 images 开始的相对路径.使用分组即可.
    std::regex img_regex("(<img [^>]*src=["']{1})([^"']*)\\(images\\[^"']*["']{1}[^>]*>)");
    std::smatch color_match;
    std::string rep = "$1$3";
    std::string tmp = std::regex_replace(kHtmlSnippet,img_regex,rep);
    std::cout << tmp << std::endl;

小例讲解

【1】

a.*c

匹配以a为开头,c为结尾的字符串,其中. 代表任何字符,* 代表零次或者多次

【2】

ab+c

匹配以a为开头,c为结尾,并且其中只出现一次或者多次b的字符串,其中+ 代表前面一个字符匹配一次或者多次

【3】

ab{2,3}c

匹配以a为开头,c为结尾,并且其中只出现2次到3次b的字符串,{} 一般用来定义匹配长度

【4】

a:?w+

a为开头,第二个字符”:”出现的次数0次或者1次,接下来多次匹配字母或数字或下划线或汉字,其中? 表示前面的字符匹配0次或者1次

【5】

"([^"]*)"

匹配双引号之间的数据
如 “abc” “fsds ,werw”
即 “ 多个字符,但是不包含引号 ” , 即 匹配字符串,开头是”,结尾是”,中间是没有”的字符串(零次或多次除了”的字符),其中^意思为除了什么字符, 注意转义字符 , ” 为匹配引号,[...]*中括号里面匹配零次或多次

【6】

w+|"([^"]*)"

解释:

加了 | 或运算 。即 两个表达式 
1.w+		匹配一次或者多次字母或数字或下划线或汉字
2."([^"]*)"	同【5】!
因此,如果样本为:abc,dfse,"few,few,f"
结果为:abc dfse "few,few,f"
此例也可改为:[^," ]+|"([^"]*)" ,因为样本中只有 , 和 “ 两种特殊字符,所以可以排除法去匹配,匹配一次或多次除了,”的字符

【7】

w+:(w+|"[^"]*")

以:为连接符连接成一组,按空格分隔,但不分隔引号中的空格
样本:name:Lily age:23 class:"class 1"
匹配结果:name:Lily age:23 class:"class 1"
分解成两块来匹配,第一块为冒号前部,w+,匹配一次或多次字母或数字或下划线或汉字。第二块为6.案例所述的。两块结合,中间加上:
w+ : w+|"[^"]*"

【8】

(w|.)+[^,]|"[^"]*"|w

如果数据是这样 11211,210161,"SHRINK FILM, 23 W X .0015MIL",49.95,RM1 ,1
需要处理成如下格式的数据: 11211 210161 "SHRINK FILM, 23 W X .0015MIL" 49.95 RM1 1

解释:分为三部分解析
1.(w|.)+[^,]	匹配一次或多次 字母或数字或下划线或汉字
		(w)或者是”.”号的字符,并且最后字符不是”,”
		(...)+ 表示括号中的字符允许出现一次或者多次
		[^,]  表示除了”,”字符,即以”,”结束
2."[^"]*"	匹配开头结尾是”的字符(串),即如果不是”字
		符的话都是引号中的字符
3.w		匹配有且仅有一次字母或数字或下划线或汉字

三部分用 | 来连接,表示三种情况任意一种符合,则表达式成立,即或运算。注意其中的转义字符使用

【9】

[^,"]+|,,|(?:"[^,"]*"[^"]*"[^"]*)"|"(?:[^"])*"

样本:your dollors,10000, 27 years old ,,”10,000”,”it is “10 Grand”,baby”,10k
匹配结果:your dollors 10000 27 years old 空字段 10,000 it is “10 Grand”,baby 10k
【难点】在于“10,000”和“it is “10 Grand”,baby”,双引号中嵌套双引号和逗号

1、[^,"]+可以获取之前用逗号和双引号分割的字段,但是这显然不足以将这七个字段完全正确的分割开; 
2、双引号中包含逗号或双引号之间的文本,"(?:[^"]|"")*" 
3、双引号嵌套:如果是双层嵌套,可以用表达式"[^,"]*"[^"]*"[^"]*"

最终:[^,"]+|,,|(?:"[^,"]*"[^"]*"[^"]*)"|"(?:[^"])*"    

分解:
[^,"]+  			#普通字段
,,  				#空字段
(?:"[^,"]*"[^"]*"[^"]*")  	#双层双引号嵌套
"(?:[^"])*"            		#双引号嵌套逗号

【10】

[^/^[^,](w)+s?:(s?#?)(w+|[(d|,|s)+]|"[^"]+")+

样本://#_drag: 1, #command : #killApp, #delay: 20, #path : "D:FLFQ_SOFTLauncher EXE v_2.2.5launcher.exe", #winTitle : "Launcher", #closeErrors : 1

匹配结果:
#_drag: 1
#command : #killApp
#delay: 20
#path : "D:FLFQ_SOFTLauncher EXE v_2.2.5launcher.exe"
#winTitle : "Launcher"
#closeErrors : 1
两个部分,以:为切分点
	1.	[^/^[^, ](\w)+\s?
			匹配字符串,开头不是/, [ , 或者空格的,接着是一个或多个 字母或数字或
			下划线或汉字 的字符串,最后0个或1个空格
	2.	(s?#?)(w+|[(d|,|s)+]|"[^"]+")+
			(s?#?)  匹配字符串,开头有0个或者1个空格,接下来有0个或1个#,
			接下来的字符串分情况讨论:
				1)w+		一个或多个 字母或数字或下划线或汉字 的字符串
				2)[(d|,|s)+]	以[ ... ]为数据结构的字符串,其中包括一个或多个 数字,逗号,空格 
				3)"[^"]+"	以” ... “为数据结构的字符串,其中包括不带引号的任何字符(串)
			1)2)3)三种情况或运算,匹配1次或者多次,套用( ... )+
	两部分以:连接在一起进行配对

【11】

#?w+|d[^s]+|"[^"]+"|[(d|,|s)+]

解释:

样本: 		#path : "D:FLFQ_SOFTLauncher EXE v_2.2.5launcher.exe"
		 #winTitle : "Launcher"
		 #clientRect: [0, 0, 1024, 768]
匹配结果:
"D:FLFQ_SOFTLauncher EXE v_2.2.5launcher.exe"
"Launcher"
[0, 0, 1024, 768]

分四个部分进行或运算匹配
	1.	#?w+
		开头0个或一个#,一个或多个 字母或数字或下划线或汉字
	2.	d[^s]+
		有一个数字的,后面不带空格的字符串
	3.	"[^"]+"
		“...”的字符串,其中包含不带“的字符串
	4.	[(d|,|s)+]
		[...]的字符串,其中包含一个或多个 数字、空格、逗号
		四个表达式一起或运算匹配到aaa:bbb中的bbb字符串
		

参考

https://blog.csdn.net/qq_30034925/article/details/70216525 正则表达式详细用法
http://help.locoy.com/Document/Learn_Regex_For_30_Minutes.htm 正则表达式30分钟入门教程
https://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html 最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等
https://blog.csdn.net/fengbingchun/article/details/54835571 正则表达式简介及在C++11中的简单使用
https://blog.csdn.net/fangjin_kl/article/details/79803120 C++11 之 regex 正则表达式
https://blog.csdn.net/infoworld/article/details/50946545 [C/C++11][初级][使用正则表达式库regex]
https://blog.csdn.net/AirTesla/article/details/65936559 正则表达式—解析CSV文件

PS

此篇博文内容编写于2018年12月5日。这次重新排版上传供读者阅读参考,感谢~!

原文地址:https://www.cnblogs.com/sharpeye/p/15331867.html