.NET正则基础之——.NET正则匹配模式

阅读更多

1 概述

匹配模式指的是一些可以改变正则表达式匹配行为的选项或修饰符。不同的语言支持的匹配模式不同,使用的方式也不同。

一般可分为全局和内联两种。下面主要介绍.NET中的匹配模式,其它语言的匹配模式,后续视情况补充。

2 匹配模式

2.1 全局匹配模式和内联匹配模式概述

.NET中的全局匹配模式是通过RegexOptions 枚举值指定的,可以按位“或”进行组合,全局匹配模式只能作用于整个正则表达式。全局匹配模式提供的模式更多,可以灵活的动态指定匹配模式。

而内联匹配模式是通过在正则表达式中,使用(?imnsx-imnsx:)(?imnsx-imnsx)的分组构造来改变正则表达式的匹配行为的。内联匹配模式更灵活、简洁,但是提供的模式较少。

下表摘自MSDN,部分说明做了修改。

RegexOption 成员

内联字符

说明

None

N/A

指定不设置任何选项。

IgnoreCase

i

指定不区分大小写的匹配。

Multiline

m

指定多行模式。更改 ^ $ 的含义,以使它们分别与任何行的开头和结尾匹配,而不只是与整个字符串的开头和结尾匹配。

ExplicitCapture

n

指定唯一有效的捕获是显式命名或编号的 (?<name>…) 形式的组。这允许圆括号充当非捕获组,从而避免了由 (?:…) 导致的语法上的笨拙。

Compiled

N/A

指定正则表达式将被编译为程序集。生成该正则表达式的 Microsoft 中间语言 (MSIL) 代码;以较长的启动时间为代价,得到更快的执行速度。

Singleline

s

指定单行模式。更改句点字符 (.) 的含义,以使它与每个字符(而不是除 \n 之外的所有字符)匹配。

IgnorePatternWhitespace

x

指定从模式中排除非转义空白并启用数字符号 (#) 后面的注释。请注意,空白永远不会从字符类中消除。

RightToLeft

N/A

指定搜索是从右向左而不是从左向右进行的。具有此选项的正则表达式将移动到起始位置的左边而不是右边。

ECMAScript

N/A

指定已为表达式启用了符合 ECMAScript 的行为。此选项仅可与 IgnoreCase Multiline 标志一起使用。将 ECMAScript 同任何其他标志一起使用将导致异常。

CultureInvariant

N/A

指定忽略语言中的区域性差异。

2.2 全局匹配模式

下面根据各种模式使用的频率进行讲解。

2.2.1 IgnoreCase 忽略大小写

几乎所有支持正则的语言中都提供了这一模式,是应用最多的模式之一,同时也是被“滥”用最多的模式之一。

开启忽略大小写模式,则字符可以同时匹配大写或小写形式。比如在此模式下,正则表达式“
”可同时匹配“
”和“

但并不是所有的字符都有大小写形式,所以在书写的正则中,如果不存在可区分大小写形式的元字符或是字符序列时,开启这一模式是没有任何意义的。

比如替换一般的html标签的正则表达式

string result = Regex.Replace(srcStr, @"<[^>]*>", "", RegexOptions.IgnoreCase);

因为<[^>]*>没有哪一个元字符或是字符序列具有大小写形式,所以这里的RegexOptions.IgnoreCase是多余的,用在这里虽然不会改变匹配结果,但是会降低匹配效率,同时这也不是一个好的习惯。

只有在正则表达式中,注意是正则表达式中,而不是待匹配的源字符串中,涉及到大小写形式的元字符或是字符序列时,才使用IgnoreCase模式。

2.2.2 Multiline 多行模式

多行模式改变的是“^”和“$”的匹配行为,使“^”和“$”不仅可以匹配整个字符串的开始和结束位置,还可以匹配每行的开始和结束位置。

首先说明一下“行”的范围。虽然我们在程序中习惯用“\r\n”来表示换行,但实际上“\r”和“\n”是不相关的两个字符,一个表示回车,一个表示换行。由于历史原因,“\r”并不是所有系统都支持的,所以“行”是由“\n”来分割的,其中“\n”属于前一“行”,而不属于后一“行”。

举例来说,字符串“a\r\nbc\r\n”共有三行,“a\r\n”为一行,“bc\r\n”为一行,最后还有一个“”空行。

2.2.2.1 在不开启多行模式情况下,“^”和“$”匹配范围

^”的匹配范围

MatchCollection mc = Regex.Matches("a\r\nbc\r\n", @"^");

foreach (Match m in mc)

{

richTextBox2.Text += "匹配内容:" + m.Value + " 匹配开始索引:" + m.Index + " 匹配长度:" + m.Length + "\n";

}

/*--------输出--------

匹配内容: 匹配开始索引:0 匹配长度:0

*/

$”的匹配范围

MatchCollection mc = Regex.Matches("a\r\nbc\r\n", @"$");

foreach (Match m in mc)

{

richTextBox2.Text += "匹配内容:" + m.Value + " 匹配开始索引:" + m.Index + " 匹配长度:" + m.Length + "\n";

}

/*--------输出--------

匹配内容: 匹配开始索引:6 匹配长度:0

匹配内容: 匹配开始索引:7 匹配长度:0

*/

注意:这里需要注意的是,在没有开启多行模式时,字符串结尾如果是“\n”,那么“$”是可以匹配两个位置的,一个是“\n”前的位置,一个是字符串结束位置。字符串结尾如果不是“\n”,那么“$”就只匹配字符串结束位置。

MatchCollection mc = Regex.Matches("a\r\nbc\r", @"$");

foreach (Match m in mc)

{

richTextBox2.Text += "匹配内容:" + m.Value + " 匹配开始索引:" + m.Index + " 匹配长度:" + m.Length + "\n";

}

/*--------输出--------

匹配内容: 匹配开始索引:6 匹配长度:0

*/

2.2.2.2 在开启了多行模式后,“^”和“$”匹配范围

^”的匹配范围

MatchCollection mc = Regex.Matches("a\r\nbc\r\n", @"^", RegexOptions.Multiline);

foreach (Match m in mc)

{

richTextBox2.Text += "匹配内容:" + m.Value + " 匹配开始索引:" + m.Index + " 匹配长度:" + m.Length + "\n";

}

/*--------输出--------

匹配内容: 匹配开始索引:0 匹配长度:0

匹配内容: 匹配开始索引:3 匹配长度:0

匹配内容: 匹配开始索引:7 匹配长度:0

*/

$”的匹配范围

MatchCollection mc = Regex.Matches("a\r\nbc\r\n", @"$", RegexOptions.Multiline);

foreach (Match m in mc)

{

richTextBox2.Text += "匹配内容:" + m.Value + " 匹配开始索引:" + m.Index + " 匹配长度:" + m.Length + "\n";

}

/*--------输出--------

匹配内容: 匹配开始索引:2 匹配长度:0

匹配内容: 匹配开始索引:6 匹配长度:0

匹配内容: 匹配开始索引:7 匹配长度:0

*/

2.2.2.3 匹配结果分析

^”匹配结果分析

在不开启多行模式时,“^”只匹配字符串的开始位置,也就是位置0

在开启了多行模式后,“^”匹配字符串开始位置和每个“\n”之后的行起始位置。

$”匹配结果分析

在不开启多行模式时,如果字符结尾是“\n”,那么“$”会匹配结尾“\n”之前和结束两个位置。

在开启多行模式后,“$”匹配每行“\n”之前的位置和字符串结束位置。

需要注意的是,在.NET中,无论是否开启多行模式,“^”和“$”匹配的都只是一个位置,是零宽度的。其它语言中“^”和“$”的意义可能会有所不同。

只有在正则表达式中涉及到多行的“^”和“$”的匹配时,才使用Multiline模式。

2.2.2.4 应用举例

典型应用一(参考 正则中加字符的问题):

需求描述:

fffffffffff

fffffffffff

dfdfdfdf

erererere

ferewfdfds

每行后面加一个“ttt”即为

fffffffffffttt

fffffffffffttt

dfdfdfdfttt

ererererettt

ferewfdfdsttt

代码实现:

string result = Regex.Replace(yourStr, @"^.*$", "$0ttt", RegexOptions.Multiline);

典型应用二

需求描述:

源字符串

CODE39/CODE93:

A-Z

space,-,.,$,/,+,%

CODE128A:

A-Z

0-9

space,!,",#,$,%,&,…,(,)*,+,逗号,-,.,/, <,=,>,?,@,[,],^,_

CODE128B:

A-Z

a-z

0-9

space,!,",#,$,%,&,…,(,)*,+,逗号,-,.,/, <,=,>,?,@,[,],^,_,{,},|,~

CODE2of5:

0-9

说明:

CODE128A:->条码类别

A-Z

0-9

space,!,",#,$,%,&,…,(,)*,+,逗号,-,.,/, <,=,>,?,@,[,],^,_->表示范围

要求分别匹配出条码类别和表示范围

代码实现:

MatchCollection mc = Regex.Matches(yourStr, @"(?[^\n:]+):\s*(?(^(?!\s*$).*$\n?)*)", RegexOptions.Multiline);

foreach (Match m in mc)

{

richTextBox2.Text += "条码类别: \n" + m.Groups["type"].Value + "\n";

richTextBox2.Text += "表示范围: \n" + m.Groups["range"].Value + "\n";

}

/*--------输出--------

条码类别:

CODE39/CODE93

表示范围:

A-Z

space,-,.,$,/,+,%

条码类别:

CODE128A

表示范围:

A-Z

0-9

space,!,",#,$,%,&,,(,)*,+,逗号,-,.,/, <,=,>,?,@,[,],^,_

条码类别:

CODE128B

表示范围:

A-Z

a-z

0-9

space,!,",#,$,%,&,,(,)*,+,逗号,-,.,/, <,=,>,?,@,[,],^,_,{,},|,~

条码类别:

CODE2of5

表示范围:

0-9

*/

2.2.3 Singleline 单行模式

单行模式改变的是小数点“.”的匹配行为,使小数点可以匹配包含换行符“\n”在内的任意一个字符。

这是一个很不幸的命名,总让人误会它与Multiline多行模式是有关联的,而事实上它改变的是小数点的匹配行为,与Multiline多行模式没有任何关联,由于历史原因,这一不幸的命名被保留了下来。使用时需要注意。

单行模式通常在匹配有换行的文本时使用,采用小数点+单行模式的方式匹配任意字符,在.NET中是效率最高的。参考 正则基础之——小数点

典型应用:

源字符串:

There is one obvious advantage:

You've seen it coming!

Buy now and get nothing for free!

Well, at least no free beer. Perhaps a bear,

if you can afford it.

Now that you've got...

your bear, you have to admit it!

No, we aren't selling bears.

需求:取

标签之间的内容

代码实现:

MatchCollection mc = Regex.Matches(yourStr, @"]*>(?:(?!", RegexOptions.Singleline|RegexOptions.IgnoreCase);

你可能感兴趣的:(.net,正则表达式,Microsoft)