sharplook夏洛克做为专业的日志采集分析系统,涉及的技术点,从后到前着实很多,内容也较为复杂。正则做为日志解析的手段,起着举足轻重的做用,在此小生将晦涩难懂的内容,拆解出来以便学习之用。javascript
在上一篇文章中,咱们已经学习了正则表达式的字符匹配,介绍了模糊匹配、字符组和量词。正则表达式就是匹配模式,要么匹配字符,要么匹配位置,牢记这个基准。本章小生将介绍位置匹配,将分红如下内容进行介绍:java
位置能够理解为字符之间的位置,也能够称为锚点。如图,箭头所指的位置:正则表达式
在ES5中,共有6个锚:^
、$
、\b
、\B
、(?=p)
、(?!p)
工具
^$\b\B(?=a)(?!b)
其可视化的形式以下:其可视化的形式以下:post
^
和 $
^
(脱字符)匹配开头的位置,在多行匹配中匹配行开头。学习
$
(美圆符)匹配结尾的位置,在多行匹配中匹配行结尾。spa
好比咱们把字符串的开头和结尾替换为#
,就是将位置替换为字符:日志
let result = 'lemon'.replace(/^|$/g, '#'); console.log(result); // => #lemon#
多行匹配模式(增长修饰符 m
)时,此是行的概念,这一点须要咱们注意:code
let result = 'I\nlove\njavascript'.replace(/$|^/gm, '#'); console.log(result); /* #I# #love# #javascript# */
\b
和 \B
\b
是单词边界符,具体为\w
与 \W
之间的位置,也包括\w
与 ^
之间的位置,和\w
和 $
之间的位置。regexp
好比,咱们经过字符串替换字符串中的\b
位置为#
来进行分析:
let result = '[JS] Lesson_01.mp4'.replace(/\b/g, '#'); console.log(result); // => [#JS#] #Lesson_01#.#mp4#
具体怎么匹配成这样的? 接下来咱们慢慢来分析。
首先咱们须要知道,\w
是字符组 [a-zA-Z0-9_]
的简写,也就是\w
是字母、数字和下划线中的任何一个。而 \W
是排除字符组 [^a-zA-Z0-9_]
的简写形式,即\W
是 \w
之外的任何一个字符。
咱们再来看咱们的结果[#JS#] #Lesson_01#.#mp4#
中的每个#
的由来:
[
和 J
,是 \W
与 \w
之间的位置。S
与 ]
,是 \w
与 \W
之间的位置。L
,是 \W
与 \w
之间的位置。1
与 .
,是 \w
与 \W
之间的位置。.
与 m
,是 \W
与 \w
之间的位置。4
是 \w
,即 \w
与 $
之间的位置。知道了 \b
的概念以后,接下来 \B
就很好理解了。\B
就是 \b
的反面意思,非单词边界,例如上例子中除去 \b
的位置以外,余下的就都是 \B
的位置了。具体来讲就是 \w
与 \w
、 \W
与 \W
、^
与 \W
、\W
与 $
之间的位置。
好比,上例子中,把全部 \B
替换成 #
:
let result = '[JS] Lesson_01.mp4'.replace(/\B/g, '#'); console.log(result); // => #[J#S]# L#e#s#s#o#n#_#0#1.m#p#4
(?=p)
和 (?!p)
(?=p)
,其中 p
是一个子模式,即 p
前面的位置,或者说,该位置后面的字符要匹配 p
。好比(?=l)
,表示 l
字符前面的位置,例如:
let result = 'lemon'.replace(/(?=l)/g, '#'); console.log(result); // => #lemon
而 (?!p)
就是(?=p)
的反面意思,好比:
let result = 'lemon'.replace(/(?!l)/g, '#'); console.log(result); // => l#e#m#o#n#
两者的学名分别是positive lookahead 和 negative lookahead。中文意思分别为正向先行断言和负向先行断言。ES5以后的版本,会支持positive lookbehind 和 negative lookbehind。意思是正向后行断言和负向后行断言。具体是(?<=p)
和 (?<!p)
。例如:
let result = 'lemon'.replace(/(?<=l)/g, '#'); console.log(result); // => l#emon
表示该位置以前的字符要匹配 l
表达式。而 (?<!p)
为:
let result = 'lemon'.replace(/(?<=l)/g, '#'); console.log(result); // => #le#m#o#n#
表示该位置以前的字符不能匹配 l
。
其实 (?=p)
和 ^
同样好理解,将其理解成 p
前面的那个位置便可,其余相似。
对于位置的理解,咱们能够将其理解成空字符 ""
。 好比lemon
字符串能够写成以下的形式:
'lemon' === '' + 'l' + 'e' + 'm' + 'o' + 'n'+ '';
也能够写成以下:
'lemon' === '' + 'lemon' + '';
所以,把 ^lemon$
写成 ^^lemon$$$
,是没有任何问题的:
let result = /^^lemon$$/.test('lemon'); console.log(result); // => true
甚至能够写成更复杂的:
let result = /(?=le)^^le(?=\w)mon$\b\b$/.test('lemon'); console.log(result); // => true
也就是说字符之间的位置,能够写成多个。
把位置理解成空字符,是对位置很是有效的理解方式。
本节介绍了位置的匹配,须要诸君理解 ^
、$
、\b
、\B
、(?=p)
、(?!p)
、(?<=p)
、(?<!p)
中的位置匹配的用法。
本文中的正则表达式转化为关系图来展现的工具是Regexper
此文主要参考和学习了老姚的《JavaScript 正则表达式迷你书》,内容清晰明了,在此很是感谢老姚的 free精神,致敬。
[1] 老姚 著《JavaScript 正则表达式迷你书》