欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

正则表达式基本用法

程序员文章站 2022-03-25 17:57:03
说到正则表达式,大家就会想到那像火星文一样的正则表达式字符串。虽然看起来很奇怪,但是一个个都搞清楚那些东西分别表示什么意思的时候,会发现这东西其实也不难。说干就干,我们来一个个的理解。 先弄点数据 先来个最简单的开个味,太深了都没有兴趣往下看了 没有任何的正则表达式的元字符(也就是保留字),http ......

说到正则表达式,大家就会想到那像火星文一样的正则表达式字符串。虽然看起来很奇怪,但是一个个都搞清楚那些东西分别表示什么意思的时候,会发现这东西其实也不难。说干就干,我们来一个个的理解。

先弄点数据

string input = "http://www.tansea.cn/23 233【个人博客】23333【http©双子宫殿】";
list<string> pattern = new list<string>();

先来个最简单的开个味,太深了都没有兴趣往下看了

pattern.add("http");//常量匹配 result = 2

没有任何的正则表达式的元字符(也就是保留字),http在input里面有2个,所以匹配到了2条

基础篇

一、基本语义描述符

1、\d(数字字符)与\d(非数字字符)

pattern.add("233\\d");//匹配233+数字字符 result=1
pattern.add("233\\d");//匹配233+非数字字符 result=1

2、\w(字母数字下划线)与\w(非字母数字下划线)

pattern.add("\\w");//匹配字母+数字+下划线 result=36
pattern.add("\\w");//不匹配字母+数字+下划线 result=11

注意:实测\w是能匹配到中文的

3、\s(空白字符)与\s(非空白字符)

空白字符包括制表符、换行符、垂直制表符、换页符、回车符

正则表达式基本用法
pattern.add("\t");//匹配制表符 等价于\x09
pattern.add("\n");//匹配换行符 等价于\x0a
pattern.add("\v");//匹配垂直制表符 等价于\x0b
pattern.add("\f");//匹配换页符 等价于\x0c
pattern.add("\r");//匹配回车符 等价于\x0d
pattern.add("\\s");//匹配任何空白字符 等价于[\t\n\v\f\r]
pattern.add("\\s");//匹配任何非空白字符 等价于[\t\n\v\f\r]
正则表达式基本用法

到这里就需要说明一下了,\和\\的区别

\是c#的转义符,如果要让c#把\当字符处理,要使用\\

或者在字符串前使用@告诉c#这个字符串的反斜杠都当字符处理

pattern.add(@"\s");

注意:如果一个字符串里面有多个\,有表示转义符,也有表示字符的,那就不能在字符串之前用@,只能用\\来区分

4、.(任何字符,除\n)

pattern.add(".");//匹配除 "\n" 之外的任何字符 result=49

5、\xxx(单字节)与\uxxxx(双字节)

\xxx单字节字符,字符对应转义值可以查ascii码表

pattern.add("\x61");//匹配单字节字符(x61=a) result=2
pattern.add("\x20");//匹配单字节字符(x20=空格) result=1

\uxxxx双字节字符,除常用字符之外的所有字符,包括各种不常用字符和各国语言字符等等

pattern.add("\u00a9");//匹配双字节(u00a9=©) result=1
pattern.add("[\u4e00-\u9fa5]");//匹配双字节([\u4e00-\u9fa5]=汉字) result=8

二、定位描述符

1、^ (匹配字符串的开始位置)

pattern.add("^http");//开始位置匹配 result = 1
pattern.add("^tansea");//开始位置匹配 result = 0

input确实是以http开头的,所以匹配到了1条,而下面那条语句没有匹配到记录

2、$(匹配字符串的结束位置)

pattern.add("】$");//结束位置匹配 result = 1

3、\b(空格)与\b(非空格)

pattern.add("23\\b");//匹配23+空格 result=1
pattern.add("23\\b");//匹配23+非空格 result=2

三、重复描述符

1、*(匹配0-∞次  等价于{0,})

pattern.add("233*");//以23开头,后面接0到n个3匹配 result=3

匹配到23、233、23333三条记录

2、+(匹配1-∞次  等价于{1,})

pattern.add("233+");//以23开头,后面接1到n个3匹配 result=2

匹配到233、23333两条记录

3、?(匹配0-1次  等价于{0,1})

pattern.add("233?");//以23开头,后面接0到1个3匹配 result=3

匹配到23、233、233(23333前面部分)三条记录

4、{n}(匹配n次,n>0)

pattern.add("233{1}");//以23开头,后面接1个3匹配 result=2

匹配到233、233(23333前面部分)两条记录

5、{n,}(匹配n-∞次,n>0)

pattern.add("233{1,}");//以23开头,后面接1到无限个3匹配 result=2

匹配到233、23333两条记录

6、{n,m}(匹配n-m次,n>0 且 n<=m)

pattern.add("233{2,3}");//以23开头,后面接2到3个3匹配 result=1

匹配到23333一条记录

四、选择描述符

1、|(或操作)

pattern.add("com|cn|net");//或条件 result=1

2、[](in操作,匹配所包含的任意一个字符)

pattern.add("[人从众]");//in条件 result=1

in条件与或条件的区别:或条件是支持多字符,将一个段做为一个整体而in条件只支持单字符

pattern.add("[^人从众]");//not in条件 result=46
pattern.add("[o-t]");//between条件 匹配小写o到小写t result=8
pattern.add("[^o-t]");//not between条件 匹配非小写o到小写t result=39

五、组(...)与非捕获组(?:...)

正则表达式会将刮号里的内容单独保存成一个组,并且匹配到的组可以反向引用,\n是引用第n组

pattern.add("\\.(.{1,6})");//.开头取6个字符 result=2

结果:group[0]=.tansea group[1]=tansea 

          group[0]=.cn/23  group[1]=cn/23 

注意:/23后面是有一个空格的,是取了6个字符

如果不想把刮号里的内容保存到组,可以用非捕获组

pattern.add("\\.(?:.{1,6})");

六、贪婪与非贪婪

正则表达式默认为贪婪模式,可以在重复描述符后加上?改成非贪婪模式

pattern.add(".*233");//结果为"http://www.tansea.cn/23 233【个人博客】233"一条记录
pattern.add(".*?233");//结果为"http://www.tansea.cn/23 233"、"【个人博客】233"两条记录

七、回溯与非回溯

正则表达式默认为回溯模式,可以(?>...)改成非回溯模式

在贪婪模式情况下,非回溯模式不会再重新去匹配,而是接着继续匹配

pattern.add("(.*)233");//结果为"http://www.tansea.cn/23 233【个人博客】233"
pattern.add("(?>.*)233");//结果为空

八、正向预搜索(?=...)与反向预搜索(?<=...)

1、正向预搜索

pattern.add("\\d{3}(?=【个人博客】)");//匹配3个数字开头后面是"【个人博客】"
pattern.add("\\d{3}(?!=【个人博客】)");//匹配3个数字开头后面不是"【个人博客】"

2、反向预搜索

pattern.add("(?<=【个人博客】)\\d{3}");//匹配"【个人博客】"开头后面是3个数字
pattern.add("(?!<=【个人博客】)\\d{3}");//匹配不是"【个人博客】"开头后面是3个数字

可以看出来,当判断条件在后面时,我们用的是正向预搜索,反之则相反。

预搜索刮号内的内容不会匹配

来看看结果吧

正则表达式基本用法
pattern.foreach(p =>
{
    matchcollection matches = regex.matches(input, p);
    console.writeline("count:" + matches.count);
    foreach (match item in matches)
        //console.writeline("value:" + item.groups[0].value);
        console.writeline("value:" + item.groups[0].value + "=>" + item.groups[1].value);
});
正则表达式基本用法

实战篇

一、escape和uescape

正则表达式基本用法
string input = @"\dhttp://www.tansea.cn2017";
string pattern = "\\d";
string replacement = "x";
string split = ":|/|\\.";
//\d是元符号,将元符号转换成原义解释
string escapepattern = regex.escape(pattern);
console.writeline(regex.match(input, escapepattern).groups[0].value);//result=\d
//\\d是原义,将原义转换成元符号解释
string unescapepattern = regex.unescape(escapepattern);
console.writeline(regex.match(input, unescapepattern).groups[0].value);//result=2
正则表达式基本用法

二、ismatch

regex.ismatch(input, pattern);//是否找到匹配项

三、match

match match = regex.match(input, pattern);//返回匹配到的第一项
console.writeline(match.value);

四、matches

matchcollection matches = regex.matches(input, pattern);//返回匹配到的所有项
foreach (match item in matches)
    console.writeline(item.value);

五、replace

正则表达式基本用法
console.writeline(regex.replace(input, pattern, replacement));//用指定的字符串替换匹配到的项
console.writeline(regex.replace(input, pattern, m =>
{
    string result = string.empty;
    switch (m.value)
    {
        case "2": result = "贰"; break;
        case "0": result = "零"; break;
        case "1": result = "壹"; break;
        case "7": result = "柒"; break;
    }
    return result;
}));//用委托返回的字符串替换匹配到的项
正则表达式基本用法

六、split

list<string> inputs = regex.split(input, split).tolist();//以匹配到的项的位置为基本,拆分字符串
inputs.foreach(i => console.writeline(i));