正则表达式(一)—— 正则表达式入门

正则表达式入门

完整的正则表达式由两种字符构成。特殊字符称为“元字符”,其他称为“文字”或者是普通文本字符。

为了便于理解,我们可以把正则表达式想象为普通的语言,普通字符对应普通语言中的单词,而元字符对应语法。根据语言的规则,按照语法把单词组合起来,就会得到能传达思想的文本。

特殊字符正则表达式记忆方式
换行符\nnew line
换页符\fform feed
回车符\rreturn
空白符\sspace
制表符\ttab
垂直制表符\vvertical tab
回退符[\b]backspace,之所以使用[]符号是避免和\b重复

 

匹配区间正则表达式记忆方式
除了换行符之外的任意字符.句号,除了句子结束符
单个数字,[0-9]\ddigit
除了[0-9]\Dnot digit
包括下划线在内的单个字符,[A-Za-z0-9_]\wword
非单字字符\Wnot word
匹配空白字符,包括空格、制表符、换页符和换行符\sspace
匹配非空白字符\Snot space
匹配一个词的边界\bboundary
匹配一个非单词边界\Bnot boundary

 

\b和\B例子:

/\bm/匹配“moon”中的‘m’;

/oo\b/并不匹配"moon"中的’oo’,因为’oo’被一个“字”字符’n’紧跟着。

/oon\b/匹配"moon"中的’oon’,因为’oon’是这个字符串的结束部分。这样他没有被一个“字”字符紧跟着。

/\w\b\w/将不能匹配任何字符串,因为在一个单词中间的字符永远也不可能同时满足没有“字”字符跟随和有“字”字符跟随两种情况。

/\Boo/匹配"noonday"中的’oo’, 而/y\B/匹配"possibly yesterday"中的’yes‘。

 

最容易理解的脱字符号 ^美元符号 $
正则表达式cat寻找的是一行文本中任意位置的cat。但是^cat只寻找行首的cat——^用来把匹配文本“锚定”在这一行的开头。同样,cat$只寻找位于行末的cat。

脱字符号^和美元符号$的特别之处在于,它们匹配的是一个位置,而不是具体的文本。

字符组

如果我们需要搜索的单词是grey,同时又不确定它是否写作“gray”,就可以使用正则表达式结构体[...]。它允许使用者列出在某处期望匹配的字符,通常被称作字符组。 gr[ea]y的意思是:先找到g,跟着是一个r,然后是一个a或者e,最后是一个y。

例如123456匹配1到6中的任意一个数字。这个字符组可以作为H[123456]的一部分,用来匹配<H1><H6>。在搜索html代码时很有用。

在字符组内部,字符组元字符 - 表示一个范围:H[1-6]H[123456]是完全一样的。0-9a-z常用作匹配数字和小写字母的简便方法。多重范围也是允许的,例如[0123456789abcdefABCDEF]可以写作[0-9a-fA-F],可用于处理十六进制数字。

⚠️:只有在字符组内部,连字符才是元字符。否则它就只能匹配普通的连字符号。 其实,即使在字符组内部,它也不一定就是元字符。如果 连字符 出现在字符组放入开头,它表示的就是一个普通字符,而不是一个范围。同样的道理,问号也通常被当作元字符处理,但在字符组中则不是如此。例如[0-9A-Z_!?]里面,真正的特殊字符只有那两个连字符。

小发现:

/[ads]/.test()   // true

看到这里我觉得很奇怪了,为啥这里test结果为true?

我们再看另一个?:

var reg = /[ads]/;
reg.exec()
// 这里我们得到一个数组
// ["d", index: 2, input: "undefined", groups: undefined]

从这个例子可以发现如果没有制定匹配内容,会匹配undefined这个字符串,导致匹配了内容。如果我们是这样的:/[aaa]/.test()得到的结果就会是false了。

 

排除性字符组

[^…]取代[…],这个字符组就会匹配任何未列出的字符。

例如,[^1-6]匹配除了1到6以外的任何字符。 这个字符组中开头的^表示 排除,所以这里列出的不是希望匹配的字符,而是不希望匹配的字符。

再看另一个例子,要匹配一对单词中字母q后面不是u的单词:q[^u]

用点号匹配任意字符

元字符.是用来匹配任意字符的字符组的简便写法。

如果需要匹配06/17/52、06-17-52或者06.17.52,可以用03[-./]19[-./]76来匹配。若需要匹配间隔为任意字符的,可以用03.19.76来匹配。

在这里要注意的是,在03[-./]19[-./]76中,点号.并不是元字符(⚠️在字符组里面和外面,元字符的定义和意义是不同的)。这里的连字符-同样也不是元字符,因为它们紧贴在[或者[^之后。如果连字符不在字符组的开头,例如[.-/],这个就是用来表示范围的。

匹配任意子表达式

| 的意思是。我们回头来看看gr[ea]y的例子,还能写作grey|gray或者gr(e|a)y。注意gr[e|a]y不符合要求,因为在字符组中,|只是一个和ea一样的普通字符。

一个字符组只能匹配目标文本中的单个字符,而每个多选结构自身都可能是完整的正则表达式,都可以匹配任意长度的文本。

字符组基本可以算是一门独立的微型语言,而多选结构是“正则表达式语言主体”的一部分。

忽略大小写

-i表示进行忽略大小写的匹配

 

总结

  1. 在字符组内部,元字符的定义规则是不一样的。比如说,在字符组外部,点号是元字符,但在内部就是普通字符;脱字符^在字符组外部是匹配文本“锚定”在这一行的开头,在字符组内部紧接着[时会匹配任何未列出的字符,在其他情况是普通字符。

  2. 不要混淆多选项和字符组

  3. 排除型字符组是表示所有未列出字符的字符组的简便方法。[^x]的意思并不是“只有当这个位置不是x时才能匹配”,而是说“匹配一个不等于x的字符”。例如,前面的概念可以匹配一个空行,而^x则不行。

可选项元素

我们来看看 color 和 colour 的匹配。我们可以用colou?r来解决这个问题。

元字符?代表可选项。把它加在一个字符的后面,就表示此处容许出现这个字符,不过它的出现并非匹配成功的必要条件,即匹配前面的子表达式零次或一次

重新出现

+*的作用与?类似。元字符+表示之前紧邻的元素出现一次或多次,而*表示之前紧邻的元素出现任意多次,或者不出现。+*?这三个元字符,统称为量词,因为它们限定了所作用元素的匹配次数。

?一样,正则表达式中的*也是永远不会匹配失败的,区别只在于它们的匹配结果(*是贪婪匹配,?是非贪婪匹配)。

规定重现次数的范围:区间

使用元字符序列来自定义重现次数的区间:…[min,max]。这称为区间量词

变量名

标识符只能包含字母、数字以及下划线,但不能以数字开头。我们可以用[a-zA-Z_][a-zA-Z_0-9]*来匹配标识符。如果标识符的长度有限制,例如最多只能是32个字符,我们可以用到区间量词{min,max},即用{0,31}来替代最后的*

引号内的字符串

匹配引号内的字符串可用“[^“]*”

var reg = /“[^“]*”/;
reg.exec('引号外面的内容“引号里面的内容”bulabula');
// ["“引号里面的内容”", index: 7, input: "引号外面的内容“引号里面的内容”bulabula", groups: undefined]

表示时刻的文字

例如“9:17am”或“12:30pm”
[0-9]?[0-9]:[0-9][0-9](am|pm)
能匹配到“9:17am”和“12:30pm”,但也能匹配无意义的时刻,如99:99*pm。

如果小时数是一个两位数,第一位只能是1。但是1?[0-9]仍然能匹配到19,所以更好的办法应该把小时部分分为两部分处理。1[012]匹配两位数,1-9匹配一位数,结果就是(1[012]|[1-9])

我们再来看分钟数。第一位数字应该是[0-5],第二位数字应该是[0-9]。综合起来就是(1[012]|[1-9]:[0-5][0-9](am|pm))

举一反三:24小时制的写法:

(([01]?[0-9])|(2[0-3])):[0-5][0-9]

接下来我们测试下:

var reg = /(([01]?[0-9])|(2[0-3])):[0-5][0-9]/;
reg.test('20:23')   // true
reg.test('25:23')   // true

https://img-blog.csdnimg.cn/20190524145022804.gif

怎么肥事???25:23也可以?

不急,我们再看下:

reg.exec('25:23')  
// ["5:23", "5", "5", undefined, index: 1, input: "25:23", groups: undefined]

这里是匹配到了5:23.然后我想了下,改成了这样:

var reg = /(([01]+[0-9])|(2[0-3])):[0-5][0-9]/;

现在是可以的了。但是有一个缺陷,我也想匹配9:13这样的,即前面的0是可选的,这样就不支持了。

为了支持让它全部匹配,我又改成了这样:

var reg = /((^[01]?[0-9])|(^2[0-3])):[0-5][0-9]/;

这样就是可以的了。

 

子表达式

子表达式指的是整个正则中的一部分,通常是括号内的表达式,或者是括号内的表达式,或者是由|分隔的多选分支。

例如,在[^(subject|date):]中,subject|date通常被视为一个子表达式,其中的subjectdate也算得上子表达式。严格来说,sub这些字符,都算子表达式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值