- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章深入浅析正则表达式 捕获组由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
捕获组(capturing group)是正则表达式里比较常用,也是比较重要的概念,我个人觉得掌握这部分的知识是非常重要的.
这篇文章内容不会很深入,但是尽量做到简单易懂又全面。接下来的内容主要是围绕以下7个点:
1: () 捕获组 2: (?:) non capturing group 3: (?=) positive lookahead 4: (?!) negative lookahead 5: (?<=) positive lookbehind 6: (?<!) negative lookbehind 7: (?=), (?!), (?<=), (?<!)的捕获 。
1: () 捕获组 。
/go+/ 。
以上的正则表达式表示一个字母g后面跟上一个或者多个字母o,他能匹配go或者goooo。但是如果我们想+不只是运用到字母o上,而是运用到go这个整体上怎么办呢?办法就是给go加括号:
/(go)+/ 。
为了全局匹配以及不考虑大小写,我们接下来会给我们的正则加上ig,这两个flag:
1
2
|
let
reg = /(go)+
/ig
;
'go is g gogo'
.match(reg);
//
[
"go"
,
"gogo"
]
|
在上面的例子里面(go)就形成了一个捕获组(capturing group)。接下来看一个使用捕获组的例子来加深对它的理解:
1
2
3
4
5
6
|
let reg = /(\d{2}).(\d{2}).(\d{4})/;
let originString =
'10.25.2017'
;
reg.test(originString);
//true
RegExp.$1;
//10
RegExp.$2;
//25
RegExp.$2;
//2017
|
在上面这个例子里,我们有三组括号,形成了三个捕获组,正则表达式(在javaScript里就是我们的RegExp)会缓存捕获组所匹配的串,以$n表示,n就代表这第几个捕获组.
假如现在我们有一个需求:把显示格式为 10.25.2017 的时间改为 2017-10-25 格式.
我们知道String的replace()方法经常和正则表达式一起使用。在replace()方法里,我们可以直接使用捕获组的结果:
1
2
3
4
|
let
reg = /(\d{2}).(\d{2}).(\d{4})/;
let
originString =
'10.25.2017'
;
let
newString = originString.replace(reg,
'$3-$1-$2'
);
console.log(newString);
//
"2017-10-25"
|
2: (?:) non capturing group 非捕获型分组 。
有的时候我们可能只想匹配分组,但是并不想缓存(不想捕获)匹配到的结果,就可以在我们的分组模式前面加上?:。例如上面的时间的例子,我们不想捕获第一个分组的结果,就可以这么做:
1
2
3
4
5
6
|
let
reg = /(?:\d{2}).(\d{2}).(\d{4})/;
let
originString =
'10.25.2017'
;
reg.
test
(originString);
//true
RegExp.$1;
//25
RegExp.$2;
//2017
originString.match(reg);
//
[
"10.25.2017"
,
"25"
,
"2017"
, index: 0, input:
"10.25.2017"
,
groups
: undefined]
|
从上面的例子可以看出,我们的正则表达式依然是匹配的(test()的结果依然为true),但是RegExp.$1不是数字10,而是25,因为我们在第一个括号里加了?:,10就不会被捕获。match()的执行结果也会受?:的影响:match()的结果里不再有‘10'.
3: (?=) positive lookahead 正向前瞻型捕获 。
有一个句子:1 apple costs 10€. 我们想要匹配€前面的价格(这里是一个数字),但是注意不能匹配到句子开头的数字1。这种情况,就可以用到正向前瞻型捕获:
1
2
3
4
5
|
let
reg = /\d+(?=€)
/g
;
let
reg1 = /\d+
/g
;
let
str =
'1 apple costs 10€'
;
str.match(reg);
//
[
"10"
]
str.match(reg1);
//
[
"1"
,
"10"
]
|
上面的例子里面reg1就只需要匹配数字,对于数字后面跟什么并没有要求,所以它能匹配到1,10。但是reg使用了前瞻型匹配,就只能匹配到10。 或许你已经能从上面的对比里了解到什么是正向前瞻型捕获了,意思是
/x(?=y)/ 匹配x, 但是必须在x的【后面】【是】y的情况下 。
4: (?!) negative lookahead 负向前瞻型捕获 。
上面我们了解了什么是正向前瞻型匹配,从字面意思也能猜出来负向前瞻型捕获就是
/x(?!y)/ 匹配x, 但是必须在x的【后面】【不是】y的情况下 。
例如下面的例子,我们要匹配数字1,而不要€前面的2,就可以用到?!:
1
2
3
|
let
reg = /\d+(?!€)
/g
;
let
str =
'1 apple costs 2€'
;
str.match(reg); [
'1'
]
|
5: (?<=) positive lookbehind 正向后顾型捕获 。
后顾型和前瞻型正好相反,意思就是:
/(?<=y)x/ 匹配x, 但是只在【前面】【有】y的情况下 。
来看一个例子:
1
2
|
let
str =
"1 turkey costs $2"
;
console.log( str.match(/(?<=\$)\d+
/g
) );
//
[
"2"
]
|
这里的要求是前面有$的数字,所以这里匹配到了数字2,而没有1. 。
6: (?<!) negative lookbehind 负向后顾型捕获 。
负向就是与正向相反,那么负向后顾型捕获就是:
/(?<=y)x/ 匹配x, 但是只在【前面】【没有】y的情况下 。
来看一个例子:
1
2
|
let
str =
"1 turkey costs $2"
;
console.log( str.match(/(?<!\$)\d+
/g
) );
//
[
'1'
]
|
7: (?=), (?!), (?<=), (?<!)的捕获 。
默认情况下上面的前瞻后顾4种都是默认不匹配捕获组里面的内容的,也就是不匹配括号里的条件的。例如我们的正向前瞻/d+(?=€)/g,只会匹配到数字,并不会匹配到€。如果我们想要也匹配到€怎么办呢?答案就是给€也包上一个括号:
1
2
3
|
let
str =
"1 turkey costs 2€"
;
let
reg = /\d+(?=(€))/;
str.match(reg);
//
[
"2"
,
"€"
, index: 15, input:
"1 turkey costs 2€"
,
groups
: undefined]
|
这样就匹配到了数字2和它后面的€.
下面再来看看后顾型:
1
2
3
|
let
str =
"1 turkey costs $2"
;
let
reg = /(?<=(\$|£))\d+/;
console.log( str.match(reg) );
//
[
"2"
,
"$"
, index: 16, input:
"1 turkey costs $2"
,
groups
: undefined]
|
需要特别注意到的一点是,对于后顾型,虽然条件在匹配项的前面,但是匹配出来的结果顺序依然是条件在匹配项的后面。所以这里match()出来的结果是2在$的前面.
总结 。
以上所述是小编给大家介绍的正则表达式 捕获组,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢! 。
原文链接:https://segmentfault.com/a/1190000019032310 。
最后此篇关于深入浅析正则表达式 捕获组的文章就讲到这里了,如果你想了解更多关于深入浅析正则表达式 捕获组的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
最近做一个项目,由于是在别人框架里开发app,导致了很多限制,其中一个就是不能直接引用webservice 。 我们都知道,调用webserivice 最简单的方法就是在 "引用"
这是SDL2代码的一部分 SDL主函数 int main(int argc,char *argv[]) { ... ... bool quit=false; S
c 中的函数: PHPAPI char *php_pcre_replace(char *regex, int regex_len, ch
我有以下映射: public class SecurityMap : ClassMap { public SecurityMap() {
我在vue-lic3中使用了SCSS,但是有一个奇怪的错误,使用/ deep /会报告错误,我不想看到它。 代码运行环境 vue-cli3 + vant + scss 的CSS /deep/ .van
我在深入阅读 C# 时遇到了这个我能理解的内容: 当它被限制为引用类型时,执行的比较类型完全取决于类型参数被限制为什么。 但是不能理解这个: 如果进一步限制派生自重载 == 和 != 运算符的特定类型
Closed. This question is opinion-based。它当前不接受答案。 想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。 3年前关闭。
有人可以详细介绍关于自赋值的运算符重载中的 *this 和 const 例如: Class& Class::operator=(const Class& other) { a = other.
在向树中插入新节点时,如何填充闭包表的深度/长度列? ancestor 和 descendant 中的值是来自另一个表的 ID,表示要以树结构排列的页面。 关闭表: ancestor desce
现在我正在阅读“深入了解 C#”。缺少的一件事是完成一章后我可以解决的一系列问题。那会帮助我理解我刚刚学到的概念。 哪里可以找到适合 C#3.0 的问题集? 谢谢 最佳答案 你可以试试LINQ 101
TypeScript 给 JavaScript 扩展了类型的语法,我们可以给变量加上类型,在编译期间会做类型检查,配合编辑器还能做更准确的智能提示。此外,TypeScript 还支持了高级类型用
是否有一个单行代码来获取生成器并生成该生成器中的所有元素?例如: def Yearly(year): yield YEARLY_HEADER for month in range(1, 13)
所以我阅读了一些与“什么是方法组”相关的 StackOverflow 问题以及其他互联网文章,它们在底线都说了同样的话——方法组是“一组重载方法” ". 但是,在阅读 Jon Skeet 的“C# 深
有什么方法可以从子组件中获取子组件吗? 想象一下以下组件树: 应用程序 问题 问题选项(包含复选框) 问题选项(包含复选框) 问题选项(包含复选框) 我想从 App 访问问题选项以选中所有复选框。 参
class_eval 和 instance_eval 在定义方法等情况下是完全可以预测的。我也理解类的实例和类的单例(又名特征类)之间的区别。 但是 我无法弄清楚以下唯一的事情:比方说,出于某些策略目
我想出了如何将符号 rwx 部分读取/转换为 421 个八进制部分,这非常简单。但是当涉及到特殊字符时,我感到非常困惑。我们知道 -r-xr---wx 转换为 0543,但 -r-sr---wt 或
我怀疑我系统的 Java 版本有问题。某些应用程序出现段错误或内存不足或存在链接错误。如果我从源代码安装了 JDK,我会做类似“make test”的事情,看看哪些测试失败了。但是,看起来从源代码构建
如何克隆一个 repo(使用 libgit2 ) 我想做什么git clone确实,但有 libgit2 .我可能要问的是什么 git clone确实很深入。 这是我目前正在做的: 初始化一个repo
00、头痛的JS闭包、词法作用域? 被JavaScript的闭包、上下文、嵌套函数、this搞得很头痛,这语言设计的,感觉比较混乱,先勉强理解总结一下😂😂😂.
我开始玩 lubridate R 中的包。我注意到 now(tzone="EST")计算为: [1] "2015-08-25 13:01:08 EST" 而 now(tzone="PST")导致警告:
我是一名优秀的程序员,十分优秀!