正则表达式使用总结

(38) 2023-10-14 15:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说正则表达式使用总结,希望能够帮助你!!!。

正则表达式中的问号(?)

1 分组的时候,?可以不记录一些组,比如:

var str="abc";

var reg=/(?:a)b(c)/g

reg.test(str);

alert(RegExp.$1);//结果为c

此时虽然第一个小括号也满足,但是如果用?:标注之后,它不会被存入正则表达式的缓存中。

2 遇见功能,"?=",意识说目标串中肯定存在什么,比如:

var str="ab4";

var reg=/ab(?=\d)/g

alert(reg.test(str));//结果为true

意思是第三位肯定是数字;

"?!",意思说目标串中不应该存在什么

var str="ab1";

var reg=/ab(?!\d)/g

alert(reg.test(str));//结果为false

意思是目标串中的第三位不应该是数字。

正则表达式-问号的四种用法

原文符号

因为?在正则表达式中有特殊的含义,所以如果想匹配?本身,则需要转义,\?

有无量词

问号可以表示重复前面内容的0次或一次,也就是要么不出现,要么出现一次。

非贪婪匹配

贪婪匹配

在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配

string pattern1 = @"a.*c"; // greedy match

Regex regex = new Regex(pattern1);

regex.Match("abcabc"); // return "abcabc"

非贪婪匹配

在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配

string pattern1 = @"a.*?c"; // non-greedy match

Regex regex = new Regex(pattern1);

regex.Match("abcabc"); // return "abc"

几个常用的非贪婪匹配Pattern

*? 重复任意次,但尽可能少重复

+? 重复1次或更多次,但尽可能少重复

?? 重复0次或1次,但尽可能少重复

{n,m}? 重复n到m次,但尽可能少重复

{n,}? 重复n次以上,但尽可能少重复

不捕捉模式

如何关闭圆括号的捕获能力?而只是用它来做分组,方法是在左括号的后边加上:?,这里第一个圆括弧只是用来分组,而不会占用捕获变量,所以$1的内容只能是steak或者burger

正则表达式的先行断言(lookahead)和后行断言(lookbehind)

正则表达式的先行断言和后行断言一共有4种形式:

(?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion)

(?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)

(?<=pattern) 零宽正向后行断言(zero-width positive lookbehind assertion)

(?<!pattern) 零宽负向后行断言(zero-width negative lookbehind assertion)

这里面的pattern是一个正则表达式。

如同^代表开头,$代表结尾,\b代表单词边界一样,先行断言和后行断言也有类似的作用,它们只匹配某些位置,在匹配过程中,不占用字符,所以被称为"零宽"。所谓位置,是指字符串中(每行)第一个字符的左边、最后一个字符的右边以及相邻字符的中间(假设文字方向是头左尾右)。

下面分别举例来说明这4种断言的含义。

(?=pattern) 正向先行断言

代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配pattern。

例如对"a regular expression"这个字符串,要想匹配regular中的re,但不能匹配expression中的re,可以用"re(?=gular)",该表达式限定了re右边的位置,这个位置之后是gular,但并不消耗gular这些字符,将表达式改为"re(?=gular).",将会匹配reg,元字符.匹配了g,括号这一砣匹配了e和g之间的位置。

(?!pattern) 负向先行断言

代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配pattern。

例如对"regex represents regular expression"这个字符串,要想匹配除regex和regular之外的re,可以用"re(?!g)",该表达式限定了re右边的位置,这个位置后面不是字符g。负向和正向的区别,就在于该位置之后的字符能否匹配括号中的表达式。

(?<=pattern) 正向后行断言

代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配pattern。

例如对"regex represents regular expression"这个字符串,有4个单词,要想匹配单词内部的re,但不匹配单词开头的re,可以用"(?<=\w)re",单词内部的re,在re前面应该是一个单词字符。之所以叫后行断言,是因为正则表达式引擎在匹配字符串和表达式时,是从前向后逐个扫描字符串中的字符,并判断是否与表达式符合,当在表达式中遇到该断言时,正则表达式引擎需要往字符串前端检测已扫描过的字符,相对于扫描方向是向后的。

(?<!pattern) 负向后行断言

代表字符串中的一个位置,紧接该位置之前的字符序列不能匹配pattern。

例如对"regex represents regular expression"这个字符串,要想匹配单词开头的re,可以用"(?<!\w)re"。单词开头的re,在本例中,也就是指不在单词内部的re,即re前面不是单词字符。当然也可以用"\bre"来匹配。

对于这4个断言的理解,可以从两个方面入手:

1. 关于先行(lookahead)和后行(lookbehind):正则表达式引擎在执行字符串和表达式匹配时,会从头到尾(从前到后)连续扫描字符串中的字符,设想有一个扫描指针指向字符边界处并随匹配过程移动。先行断言,是当扫描指针位于某处时,引擎会尝试匹配指针还未扫过的字符,先于指针到达该字符,故称为先行。后行断言,引擎会尝试匹配指针已扫过的字符,后于指针到达该字符,故称为后行

2.关于正向(positive)和负向(negative):正向就表示匹配括号中的表达式,负向表示不匹配。

对这4个断言形式的记忆:

1. 先行和后行:后行断言(?<=pattern)、(?<!pattern)中,有个小于号,同时也是箭头,对于自左至右的文本方向,这个箭头是指向后的,这也比较符合我们的习惯。把小于号去掉,就是先行断言。

2. 正向和负向:不等于(!=)、逻辑非(!)都是用!号来表示,所以有!号的形式表示不匹配、负向;将!号换成=号,就表示匹配、正向。

我们经常用正则表达式来检测一个字符串中包含某个子串,要表示一个字符串中不包含某个字符或某些字符也很容易,用[^...]形式就可以了。要表示一个字符串中不包含某个子串(由字符序列构成)呢?

用[^...]这种形式就不行了,这时就要用到(负向)先行断言或后行断言、或同时使用。

例如判断一句话中包含this,但不包含that。

包含this比较好办,一句话中不包含that,可以认为这句话中每个字符的前面都不是that或每个字符的后面都不是that。正则表达式如下:

^((?<!that).)*this((?<!that).)*$ 或 ^(.(?!that))*this(.(?!that))*$

对于"this is the case"这句话,两个表达式都能够匹配成功,而"note that this is the case"都匹配失败。

在一般情况下,这两个表达式基本上都能够满足要求了。考虑极端情况,如一句话以that开头、以that结尾、that和this连在一起时,上述表达式就可能不胜任了。

如"note thatthis is the case"或者"this is the case, not that"等。

只要灵活运用这几个断言,就很容易解决:

^(.(?<!that))*this(.(?<!that))*$

^(.(?<!that))*this((?!that).)*$

^((?!that).)*this(.(?<!that))*$

^((?!that).)*this((?!that).)*$

这4个正则表达式测试上述的几句话,结果都能够满足要求。

上述4种断言,括号里的pattern本身是一个正则表达式。但对2种后行断言有所限制,在Perl和Python中,这个表达式必须是定长(fixed length)的,即不能使用*、+、?等元字符,如(?<=abc)没有问题,但(?<=a*bc)是不被支持的,特别是当表达式中含有|连接的分支时,各个分支的长度必须相同。之所以不支持变长表达式,是因为当引擎检查后行断言时,无法确定要回溯多少步。Java支持?、{m}、{n,m}等符号,但同样不支持*、+字符。Javascript干脆不支持后行断言,不过一般来说,这不是太大的问题。

正则无顺序匹配

String str="http://www.baidu.com?a=BBB&c=CCC&b=AAA";

regex="http://www.baidu.com.*?(?=.*?[\\&|\\?]a\\=).*(?=.*?[\\&|\\?]b\\=).*(?=.*?[\\&|\\?]c\\=).*";

System.out.println(str.matches(regex));

来源:

http://blog.csdn.net/u012047933/article/details/38365541

https://www.cnblogs.com/leezhxing/p/4333773.html

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复