正则表达式使用技巧整理

2021-09-24

测试工具

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

常用技巧

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

// 把所有 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_SOFT\Launcher EXE v_2.2.5\launcher.exe", #winTitle : "Launcher", #closeErrors : 1

匹配结果:
#_drag: 1
#command : #killApp
#delay: 20
#path : "D:\FLFQ_SOFT\Launcher EXE v_2.2.5\launcher.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_SOFT\Launcher EXE v_2.2.5\launcher.exe"
		 #winTitle : "Launcher"
		 #clientRect: [0, 0, 1024, 768]
匹配结果:
"D:\FLFQ_SOFT\Launcher EXE v_2.2.5\launcher.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日。这次重新排版上传供读者阅读参考,感谢~!