Bingo, Computer Graphics & Game Developer
基本上初步入门都是在这里正则表达式入门教程学到的,当然没有30分钟那么夸张。
许多时候如若不进行实际测试很难知道自己的正则表达式正确与否,一般我就在这里正则表达式在线测试或者Rebular直接在线测试,其实道理都一样。
从开始学习,到实际能够解读正则表达式,到真正运用正则表达式在CSS文件的解析上,我起码花了整整三天时间,甚至更多
首先说说我自己的感想,正则表达式难度不在于其各个元字符的搭配很难,而是解析的这一步很难。所以我自己结合了教程总结了如下经验。
案例1
^(\*?[-#/\*\w]+(\[[0-9a-z_-]+\])?)\s*
乍一看非常难以分解,不过我一般会这样做
^ #字符串开始
(
\*? #可选的*
[-#/\*\w]+ #"-""#""\""*""字母数字下划线或汉字"出现一次或多次
(
\[[0-9a-z_-]+\] #"["+0~9|a~z|_~空格+"]"
)? #上述字符串是可选的
)
\s* #任意多空格
上述代码不会对正则表达式产生任何的影响,因为(?= #xxx)内部的内容表明为注释,这样的缩进可以更明显的看出来内容,我个人更偏向于下面这样的用法。
// ^ 字符串开始
// (
// \*? 可选的任意出现零次或者多次的字符
// [-#/\*\w]+ "-""#""\""*""字母数字下划线或汉字"出现一次或多次
// (\[[0-9a-z_-]+\])? 可选的"["+0~9|a~z|_~空格+"]"
// )
// \s* 任意多空格
static const std::regex _RE0_ = RE(R"raw(^(\*?[-#/\*\w]+(\[[0-9a-z_-]+\])?)\s*)raw");
这样就有一个好处,在实际使用此正则表达式时,不用在表达式内部修改样式,有的OS例如Windows,会要求在每行的最后加上\
类似于这样
string test2 =
"body{\
background-color: #d0e4fe;\
}\
\
h1{\
color: orange;\
text-align: center;\
}\
\
p{\
font-family: \"Times New Roman\";\
font-size: 20px;\
}";
这对有强迫症的人来说简直是致命的,但又没有什么好的办法。所以我个人偏向于将正则表达式的注释写到对应语言的注释中。
对于元字符其实没有什么太多能够讲述的
反义
代码 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
重复
代码 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
元字符
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
要说说的就是这个反义,^这个字符如若不在[]中,那么它的意思一般就是表示从字符串开始的位置,当然如果前面没有转义字符的话。一旦跑到了[]中,那么它就代表了反义。
案例2
^([^\{]+)
// ^ 字符串开始处
// (
// [^\{]+ 除{以外其他的一个或者多个字符
// )
这里的两个^就展现了不同的含义,一开始我在这里费了不少功夫。
删除注释
有的正则表达式可以匹配得到多门语言当中各型各色的注释,以便于直接找到删除。删除注释大多数的语言注释的正则表达式都可以在这里找到。C/C++/Java因为语言相通所以注释匹配也是可以通用的。
在实际应用中,我使用/\*[^\*]*\*+([^/\*][^\*]*\*+)*/
来匹配CSS的注释,读者可以自行测试。
在实际的CSS解析中最难以理解的表达式如下^((?:'(?:\\'|.)*?'|\"(?:\\\"|.)*?\"|\([^\)]*?\)|[^\};])+)
// ^
// (
// (
// ?: 可选的:
// '(?:\\'|.)*?' 单引号围起来的内容或者任意字符 若前方有',那么需要以'结尾
// |
// \"(?:\\\"|.)*?\" 双引号围起来的内容或者任意字符 若前方有",那么需要以"结尾
// |
// \([^\)]*?\) (开始 匹配除了)以外的任意字符 字符可以出现零次或者多次[^x] 可选的)
// |
// [^\};] 匹配除了} ;以外的任意字符
// )
// + 可以有零个或者多个上述值出现
// )
这里的单引号的确是难以理解,后来才发现其实单引号不需要转义就可以直接表达自身的意思,可以对比下一行的双引号。因为有的CSS property: value;里的value是字符串/单一字母/xxx(xxx)/等等形式 如
background-color: rgb(0, 10, 20);
background-color: #123456;
background-color: red;
很种类繁多,因此需要一并写出。