正则表达式攻略

 正则表达式入门

http://manual.phpv.net/regular_expression.html

http://hi.baidu.com/ismayday/blog/item/7f5b86942741d11dd21b708f.html

 

.NET中的正则表达式是处于 System.Text.RegularExpressions 命名空间中的,该命名空间提供了正则表达式的各种强大的功能。

至于正则表达式的 字符类 ,在此就不作详细介绍。只列出几个常用的。

字符类 说明
[字符分组] 匹配指定字符分组内的任一字符。
[^字符分组] 匹配不在指定字符分组内的任一字符。
[第一个字符-最后一个字符] 匹配字符范围中的任一字符。
"w 与任何单词字符匹配。等效于 [a-zA-Z_0-9]。其中"_"表示字符"_"本身。
"W 与任何非单词字符匹配。等效于 [^a-zA-Z_0-9]。
"s 与任何空白字符匹配。等效于[ "f"n"r"t"v]。注意在""f"前有一个空格。
"S 与任何非空白字符匹配。等效于[^ "f"n"r"t"v]。
"d 与任何十进制数字匹配。等效于[0-9]。
"D 与任何非数字字符匹配。等效于[^0-9]。

下面先介绍Regex 类的常用方法和属性。

  • 方法
名称 说明
IsMatch 已重载。 指示正则表达式在输入字符串中是否找到匹配项。
Match 已重载。 在输入字符串中搜索正则表达式的匹配项,并将第一个精确结果作为单个 Match 对象返回。
Matches 已重载。 在输入字符串中搜索正则表达式的所有匹配项并返回所有成功的匹配,就像多次调用 Match 一样。
Replace 已重载。 在指定的输入字符串内,使用指定的替换字符串替换与某个正则表达式模式匹配的字符串。
Split 已重载。 在由正则表达式匹配项定义的位置将输入字符串拆分为一个子字符串数组。
  • 属性
名称 说明
CacheSize 获取或设置已编译的正则表达式的当前静态缓存中的最大项数。
Options 返回传入 Regex 构造函数的选项。
RightToLeft 获取一个值,该值指示正则表达式是否从右向左进行搜索。

其中Options是RegexOptions 枚举,它提供用于设置正则表达式选项。

注意此选项并非只能选其一,而是可以通过按位或符号"|"实现多个选项,比如:RegexOptions.Compiled | RegexOptions.IgnoreCase 是要求正则表达式既要编译为程序集,又要忽略大小写。

下面将通过实例来介绍各种方法的使用。

  • Regex.IsMatch 方法——当你只想验证格式是否符合时用此方法

using System;
using System.Text.RegularExpressions;

namespace ConsoleApp
{
   
class Program
    {
       
static void Main(string[] args)
        {
           
//定义用于验证正整数的表达式
           
// ^ 表示从字符串的首部开始验证
           
// $ 表示从字符串的尾部开始验证
            Regex rx = new Regex(@"^[1-9]"d*$", RegexOptions.Compiled);

           
double[] list ={ 12, -5, 1.2, 25697, 0, -1.1 };

           
foreach (double d in list)
            {
               
if (rx.IsMatch(d.ToString()))
                {
                    Console.WriteLine(
"数字 {0} 是正整数。", d);
                }
               
else
                {
                    Console.WriteLine(
"数字 {0} 不是正整数。", d);
                }
            }
        }
    }
}
//输出:

//数字 12 是正整数。
//数字 -5 不是正整数。
//数字 1.2 不是正整数。
//数字 25697 是正整数。
//数字 0 不是正整数。
//数字 -1.1 不是正整数。
  • Regex.Match 方法——适合你想从一段字符串中匹配出一个你想要的子串,并且得到这个子串的相关信息

using System;
using System.Text.RegularExpressions;

namespace ConsoleApp
{
   
class Program
    {
       
static void Main(string[] args)
        {
           
//定义能匹配单词 do 的表达式
            Regex rx = new Regex(@""s+do"s+", RegexOptions.Compiled | RegexOptions.IgnoreCase);

           
string[] source = { "How do you do !", "no one !" };

           
foreach (string s in source)
            {
                Match match
= rx.Match(s);

                Console.WriteLine(
"匹配到的子串为:|{0}|"n在原串的第 {1} 个位置"n子串长度:{2}",
                    match.Value, match.Index, match.Length);
                Console.WriteLine(
"------------------------------");
            }
        }
    }
}
//匹配到的子串为:| do |
//在原串的第 3 个位置
//子串长度:4
//------------------------------
//匹配到的子串为:||
//在原串的第 0 个位置
//子串长度:0
//------------------------------

可见,当没有匹配项时Match对象并不会为空,而是匹配到的字符串为空字符串,可以用Length属性或Value属性来判断是否匹配成功。

  • Regex.Matches 方法——有时你并不只是想要匹配到一个符合就满足,而是要把所有满足的子串全部找出来,那么用此方法。此方法返回一个MatchCollection集 合,该集合是只读的,并且没有公共构造函数。既然是集合,当然可以用 foreach 进行迭代,集合中存放的是Match对象到目前为止,许多的编程语言和工具都包含对正则表达式的支持,当然.NET也不例外,.NET基础类库中包含有一个名称空间和一系列可以充分发挥规则表达式威力的类。 
            正则表达式的知识可能是不少编程人员最烦恼的事儿了。如果你还没有规则表达式方面的知识的话,建议从正则表达式的基础知识入手。前参见 正则表达式语法。 

            下面就来研究C#中的正则表达式,C#中的正则表达式包含在.NET基础雷库的一个名称空间下,这个名称空间就是System.Text.RegularExpressions。该名称空间包括8个类,1个枚举,1个委托。他们分别是:
                         Capture: 包含一次匹配的结果; 
                         CaptureCollection: Capture的序列; 
                         Group: 一次组记录的结果,由Capture继承而来; 
                         GroupCollection:表示捕获组的集合
                         Match: 一次表达式的匹配结果,由Group继承而来; 
                         MatchCollection: Match的一个序列; 
                         MatchEvaluator: 执行替换操作时使用的委托; 
                         Regex:编译后的表达式的实例。 
                         RegexCompilationInfo:提供编译器用于将正则表达式编译为独立程序集的信息
                         RegexOptions 提供用于设置正则表达式的枚举值
    Regex类中还包含一些静态的方法: 
                        Escape: 对字符串中的regex中的转义符进行转义; 
                        IsMatch: 如果表达式在字符串中匹配,该方法返回一个布尔值; 
                        Match: 返回Match的实例; 
                        Matches: 返回一系列的Match的方法; 
                        Replace: 用替换字符串替换匹配的表达式; 
                        Split: 返回一系列由表达式决定的字符串; 
                        Unescape:不对字符串中的转义字符转义。

    下面介绍他们的用途:
            先看一个简单的匹配例子,我们首先从使用Regex、Match类的简单表达式开始学习。 Match m = Regex.Match("abracadabra", "(a|b|r)+"); 我们现在有了一个可以用于测试的Match类的实例,例如:if (m.Success){},如果想使用匹配的字符串,可以把它转换成一个字符串:   MesaageBox.Show("Match="+m.ToString()); 这个例子可以得到如下的输出: Match=abra。这就是匹配的字符串了。

            Regex 类表示只读正则表达式类。它还包含各种静态方法(在下面的实例中将逐一介绍),允许在不显式创建其他类的实例的情况下使用其他正则表达式类。

            以下代码示例创建了 Regex 类的实例并在初始化对象时定义一个简单的正则表达式。声明一个Regex对象变量:Regex objAlphaPatt;,接着创建Regex对象的一个实例,并定义其规则:objAlphaPatt=new Regex("[^a-zA-Z]");

            IsMatch方法指示 Regex 构造函数中指定的正则表达式在输入字符串中是否找到匹配项。这是我们使用C#正则表达式时最常用的方法之一。下面的例子说明了IsMatch方法的使用:
    if( !objAlphaPatt.IsMatch("testisMatchMethod"))
     lblMsg.Text = "匹配成功";
    else
     lblMsg.Text = "匹配不成功";
    这段代码执行的结果是“匹配成功”
    if( ! objAlphaPatt.IsMatch("testisMatchMethod7654298"))
     lblMsg.Text = "匹配成功";
    else
     lblMsg.Text = "匹配不成功";
    这段代码执行的结果是“匹配不成功”

             Escape方法表示把转义字符作为字符本身使用,而不再具有转义作用,最小的元字符集("、*、+、?、|、{、[、(、)、^、$、.、# 和空白)。Replace方法则是用指定的替换字符串替换由正则表达式定义的字符模式的所有匹配项。看下面的例子,还是使用上面定义的Regex对 象:objAlphaPatt.Replace("this [test] ** replace and escape" ,Regex.Escape("()"));他的返回结果是:this"(")"(")test"(")"(")"(")"(")"(")replace "(")and"(")escape,如果不是Escape的话,则返回结果是:this()()test()()()() ()replace()and()escape,Unescape 反转由 Escape 执行的转换,但是,Escape 无法完全反转 Unescape。

            Split方法是把由正则表达式匹配项定义的位置将输入字符串拆分为一个子字符串数组。例如:
    Regex r = new Regex("-"); // Split on hyphens.
    string[] s = r.Split("first-second-third");
    for(int i=0;i<s.Length;i++)
    {
     Response.Write(s[i]+"<br>");
    }

    执行的结果是:
    First
    Second
    Third

            看上去和String的Split方法一样,但string的Split方法在由正则表达式而不是一组字符确定的分隔符处拆分字符串。

            Match方法是在输入字符串中搜索正则表达式的匹配项,并Regex 类的 Match 方法返回 Match 对象,Match 类表示正则表达式匹配操作的结果。下面的例子演示Match方法的使用,并利用Match对象的Group属性返回Group对象:

    string text = @"public string testMatchObj string s string  match ";
    string pat = @"("w+)"s+(string)";
    // Compile the regular expression.
    Regex r = new Regex(pat, RegexOptions.IgnoreCase);
    // Match the regular expression pattern against a text string.
    Match m = r.Match(text);
    int matchCount = 0;
    while (m.Success)
    {
     Response.Write("Match"+ (++matchCount) + "<br>");
     for (int i = 1; i <= 2; i++)
     {
      Group g = m.Groups[i];
      Response.Write("Group"+i+"='" + g + "'"  + "<br>");
      CaptureCollection cc = g.Captures;
      for (int j = 0; j < cc.Count; j++)
      {
       Capture c = cc[j];
       Response.Write("Capture"+j+"='" + c + "', Position="+c.Index + "<br>");
      }
     }
     m = m.NextMatch();
    }

    该事例运行结果是:
    Match1
    Group1='public'
    Capture0='public', Position=0
    Group2='string'
    Capture0='string', Position=7
    Match2
    Group1='testMatchObj'
    Capture0='testMatchObj', Position=14
    Group2='string'
    Capture0='string', Position=27
    Match3
    Group1='s'
    Capture0='s', Position=34
    Group2='string'
    Capture0='string', Position=36

            MatchCollection 类表示成功的非重叠匹配的只读的集合,MatchCollection 的实例是由 Regex.Matches 属性返回的,下面的实例说明了通过在输入字符串中找到所有与Regex中指定的匹配并填充 MatchCollection。

    MatchCollection mc;
    Regex r = new Regex("match");
    mc = r.Matches("matchcollectionregexmatchs");
    for (int i = 0; i < mc.Count; i++)
    {
     Response.Write( mc[i].Value + " POS:" + mc[i].Index.ToString() + "<br>");
    }
    该实例运行的结果是:
    match POS:0
    match POS:20

C# Regex 深入正则表达式

正则表达式(Regular expressions)是一套语法匹配规则,各种语言,如Perl, .Net和Java都有其对应的共享的正则表达式类库。在.Net中,这个类库叫做Regex。
简单的说,Regex是从字符窗中查找匹配字符串的应用类。通过Regex,编程人员能够非常方便的从一段数据中提取自己所需要的数据信息。举一个简单的例子,让大家对Regex有个大概的了解:
Regex regex = new Regex(@"d+");
Match m = regex.Match("fox 9212gold");
Console.WriteLine(m.Value.ToString());
结果很明显,regex为我们找到了字符串”fox 9212gold”中的数字字符串,输出结果为”9212” .
对 Regex有了一个基本的概念之后,我需要告诉你一个非常好的消息,那就是Regex可以为我们做的远不止这么一点点,他是一套功能非常强大语法匹配规 则。当然,这里还有一个坏消息等着我们,那就是强大功能的语法规则自然需要大量纷繁复杂的keyword支持,这也为Regex的学习带来了极大的难度。 想要真正掌握正则表达式,可不是几个sample能够全部揭示与说明的。

创建一个Regex对象
Regex的构造函数有三种,在这里就不讨论默认构造函数了。另外两个构造函数中,一个构造函数接收正则表达式字符串作为入参,另一个以正则表达式字符串和RegexOptions作为入参。如:
 
Regex regex = new Regex("w+$");
Regex regex = new Regex("s+", RegexOptions.IgnoreCase | RegexOptions.Multiline);
RegexOptions可以为我们提供一些特殊的帮助,比如IgnoreCase能够在匹配是忽略大小写,Multiline能够调整^和$的意义,改为匹配一行的开头和结尾。
上面我们构造了一个正则表达式,只不过我们还没有用它来做任何事情,马上我们就可以通过使用下面的几个方法,实现对字符串对象的操作了。
匹配字符串
Regex有两个获取匹配的方法Match()和Matches(),分别代表匹配一个,匹配多个结果。这里就用Matches来展示一下怎么使用Regex获取匹配字符串,并将其显示出来。
 
public static void showMatches(string expression, RegexOptions option, string ms)
{
Regex regex = new Regex(expression, option);
MatchCollection matches = regex.Matches(ms);
//show matches
Console.WriteLine("////////////////----------------------------------////////////////");
Console.WriteLine(" string: "{0}"  expression: "{1}"  match result is:", ms, expression);
foreach(Match m in matches)
{ Console.WriteLine("match string is: "{0}", length: {1}",m.Value.ToString(), m.Value.Length);
}
Console.WriteLine("matched count: {0}", matches.Count);
}
方法Matched通过比较入参字符串和正则表达式,找到所有符合的结果,并将结果作为MatchCollection传出来。这样,只要简单的遍历这个collection,就可以很快的获得所有的结果。

组的概念

当你获得这样的一个字符串”最后比分是:19/24”,你肯定希望有一个正则表达式,他不单能够找到形如 data1/data2的字符串,还应该能够直接把data1,data2作为单独的结果传送出来。否则你需要再对形如”19/24”的字符串进行分析, 才能够顺利得到双方的比分。显然,正则表达式不会忽略这个问题,所以他增加了组的概念。你可以把一次搜索的结果分别放入不同的组中,并通过组名或者组的所 以分别取得这些组的结果。比如上例,我们就可以用@”("d+)/("d+)”作为表达式。来看看结果吧:
 
Regex regex = new Regex(@"(d+)/(d+)");
MatchCollection matches = regex.Matches(@"最后比分是:19/24");
//show matches
Console.WriteLine("////////////////----------------------------------////////////////");
foreach(Match m in matches)
{
//Console.WriteLine("match string is: "{0}", length: {1}", // m.Value.ToString(), m.Value.Length);
foreach(string name in regex.GetGroupNames())
{
Console.WriteLine("  capture group "{0}" value is:"{1}"" , name, m.Groups[name].Value);
}
}
Console.WriteLine("matched count: {0}", matches.Count);
输出:
////////////////----------------------------------////////////////
capture group "0" value is:"19/24"
capture group "1" value is:"19"
capture group "2" value is:"24"
matched count: 1

现在清楚了吧,Regex对象把匹配的结果放入组0中。同时,匹配的组信息也放入了对应的组中。组的名称在默认的情况下,是从1开始依次增加的整 数。0作为保留名称,专门用于指示匹配的整个字符串。既然有”默认情况”这样的概念,自然也就意味着用户可以自定义组的名称。方法很简单,在组的前面加 上:?<name>就可以了。好了,现在把前面的正则表达式修改一下,换成 @”(?<score1>"d+)/(?<score1>"d+)”,现在再看看结果:
////////////////----------------------------------////////////////
capture group "0" value is:"19/24"
capture group "score1" value is:"19"
capture group "score2" value is:"24"
matched count: 1

换成自己定义的名字了吧,哈哈!为了在今后的测试中,能够更加方便的看到所有结果,我们对前面介绍过的showMatches()做一点小小的调 整。这样,如果在表达式中包含了组的定义,我们也可以在不需要修改任何代码的情况下,直接看到所有的组信息了,调整后的方法 showMatchesPro()如下:

public static void showMatchesPro(string expression, RegexOptions option, string ms)
{
Regex regex = new Regex(expression, option);
MatchCollection matches = regex.Matches(ms);
//show matches
Console.WriteLine("////////////////----------------------------------////////////////");
Console.WriteLine(" string: "{0}"  expression: "{1}"  match result is:",ms, expression);
foreach(Match m in matches)
{
  foreach(string name in regex.GetGroupNames())
{
Console.WriteLine("  capture group "{0}" value is:"{1}"",name, m.Groups[name].Value);
}
}
Console.WriteLine("matched count: {0}", matches.Count);
// show group name
Console.WriteLine("group name count {0}", regex.GetGroupNames().Length);
foreach(string name in regex.GetGroupNames())
{
Console.WriteLine("group name :"{0}"", name);
}
}
替换字符串
Regex也提供了方便的匹配结果替换的功能。为了方便测试,我们也把他写成方法,代码如下:

public static string replaceMatch(string expression, RegexOptions option, string ms, string rep)
{
Regex regex = new Regex(expression, option);
string result = regex.Replace(ms, rep);
Console.WriteLine("////////////////----------------------------------////////////////");
Console.WriteLine("string: "{0}", expression:"{1}", replace by : "{2}"", ms, expression, rep);
Console.WriteLine("replace result string is: "{0}", length: {1}", result.ToString(), result.Length);
return result;
}

Regex.Replace通常接受两个string作为入参,第一个string为输入字符串。第二个字符串用来替代匹配字符串,它可以包含一些特殊字符串,用来代表特别转换。

特殊字符串 替换结果
$& 匹配的字符串,也可以用$0
$1, $2, . . . 匹配字符串中的对应组,用索引标示
${name} 匹配字符串中的对应组,用名称标示
$‘ 匹配位置之前的字符串
$’ 匹配位置之后的字符串
$$ 一个‘$’ 字符
$_ 输入字符串
$+ 匹配字符串的所有组中,最后一个组中的数据

是不是看了这么多怪型怪状的特殊字符串,有点头晕了?嗯,那就弄两个sample来看看结果吧!
Sample1:
replaceMatch(@""d+", RegexOptions.None, "fef 12/21 df 33/14 727/1", "<<$&>>");
输出,所有数字型的数据都被替换成了<<data>>:
////////////////----------------------------------////////////////
string: "fef 12/21 df 33/14 727/1", expression:""d+", replace by : "<<$&>>"
replace result string is: "fef <<12>>/<<21>> df <<33>>/<<14>> <<727>>/<<1>>",
length: 50

Sample2:
replaceMatch(@"("d+)/("d+)", RegexOptions.None, "fef 12/21 df 33/14 727/1", "$+");
输出,所有data1/data2匹配的数据,都被替换成了data2:
////////////////----------------------------------////////////////
string: "fef 12/21 df 33/14 727/1", expression:"("d+)/("d+)", replace by : "$+"
replace result string is: "fef 21 df 14 1", length: 16

怎么样,Regex的功能够丰富的吧!可是,也许你的需求不光这么简单,比如说,你要把”I have 200 dollars”中间的money加倍,怎么办?我晕倒,好像没有现成的东西可以用。没有关系,Regex还有更好的功能。它允许你自己定义转换公式。
 
using System.Text.RegularExpressions;
class RegularExpressions
{
static string CapText(Match m)
{
// Get the matched string.
string x = m.ToString();
// double this value
string result = (int.Parse(x) * 2).ToString();
return result;
}
static void Main()
{
string text = "i have 200 dollars";
string result = Regex.Replace(text, @"d+",new MatchEvaluator(RegularExpressions.CapText));
System.Console.WriteLine("result=[" + result + "]");
}
}
看看结果,太好了,我的钱真的变成了两倍!
但本文的目的是希望提供给大家一个方便好用的测试类,因此我们重载上面的repalceMatch方法,也允许自定义转换公式作为入参:

public static string replaceMatch(string expression, RegexOptions option, string ms,
MatchEvaluator evaluator)
{
Regex regex = new Regex(expression, option);
string result = regex.Replace(ms, evaluator);
Console.WriteLine("////////////////----------------------------------////////////////");
Console.WriteLine("string: "{0}", expression:"{1}", replace by a evaluator.", ms, expression);
Console.WriteLine("replace result string is: "{0}", length: {1}", result.ToString(), result.Length);
return result;
}
拆分字符串

Regex还提供了从匹配位置将字符串拆分的方法Split。这个方法同样具有多个重载,不过这些都不是重点,大家可以自己看文档。我们继续完成我们用于测试的方法:
public static void splitMatch(string expression, RegexOptions option, string ms)
{
Regex regex = new Regex(expression, option);
string[] result = regex.Split(ms);
Console.WriteLine("////////////////----------------------------------////////////////");
Console.WriteLine("string: "{0}", expression: "{1}", split result is:", ms, expression);
foreach(string m in result)
{
Console.WriteLine("splited string is: "{0}", length: {1}",m.ToString(), m.Length);
}
Console.WriteLine("splited count: {0}", result.Length);
}
代码简单,不多做解释。直接来一个smaple看看结果:
splitMatch(@"/",RegexOptions.None, "2004/4/25");
输出:
////////////////----------------------------------////////////////
string: "2004/4/25", expression: "/", split result is:
splited string is: "2004", length: 4
splited string is: "4", length: 1
splited string is: "25", length: 2
splited count: 3

这个文章的目的很简单:介绍Regex的几个主要功能(匹配、替换和拆分),并提供几个简单方便的测试函数。让你能够测试你对正则表达式的理解是否准确。

比如想要确认^$的作用,你可以放入这样的(input, expression)数据:
(“123”, “^"d+$”) (“123aaa456”, “^"d+”) (“123aaa456”, “123&”)

确认"d, "s, "w, "W的作用,可以这样测试:
(“123abc gc 456”, “"d+”)(“123abc gc 456”, “"s+”)
(“123abc gc 456”, “"w+”)(“123abc gc 456”, “"W+”)

比较? + *之间的区别可以用这样的数据:
(“a123 abcd”, “a"d?”) (“a123 abcd”, “a"d+”) (“a123 abcd”, “a"d*”)

javascript中正则表达式

http://www.cnblogs.com/del/archive/2009/03/05/1404200.html

 

posted @ 2009-04-01 10:33  小贱  阅读(312)  评论(0编辑  收藏  举报