正则积累

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace 正则积累
{
    class Program
    {
        static void Main(string[] args)
        {
            //Fun1();
            //Fun2();
            //Fun3();
            //Fun4();
            //Fun5();
            //Fun6();
            //Fun7();
            Fun8();
            //Regex reg = new Regex("^a.*b$");
            //string str = "aHello\nb";
            //Console.WriteLine(reg.Match(str).Value);
        }

        /// <summary>
        /// 分组引用
        /// </summary>
        static void Fun1()
        {
            string str = "'Hello'";
            string str2 = "'Hello\"";

            //在正则表达式中,\整数表示引用 第整数个括号内里文本
            //此正则表达式最后的 \1 表示引用此正则表达式第一个括号内的文本(即单引号或者双引号),此正则匹配 Hello 两边的引号一致字符串
            Regex reg = new Regex("(['\"])[a-zA-Z]*\\1");

            //匹配成功,因为Hello前面和后面都是单引号
            Match m = reg.Match(str);
            //m.Groups[0].Value其实就是m.Value
            Console.WriteLine(m.Groups[0].Value);
            //m.Groups[1].Value就是正则里第一个括号里的文本 , 既 '
            Console.WriteLine(m.Groups[1].Value);

            Console.WriteLine(reg.IsMatch(str2));

            //使用正则的Replace方法的时候,$整数表示引用 第整数个括号内里文本
            Console.WriteLine(reg.Replace("123'Hello'456", "$1"));//替换结果为"123'456"

            //以上两种引用括号内文本的方法,括号都是以左括号从左边开始计数的


            //使用括号分组,但是不算如引用计数的方法:在左括号后面加 ?:
            //reg2里面的\1应该是引用123,但是包含123的括号为(?:),所以此括号不参与引用计数,所以匹配成功
            Regex reg2 = new Regex("(?:123)*(['\"])[a-zA-Z]*\\1");
            Match m2 = reg2.Match(str);
            Console.WriteLine(reg2.IsMatch(str));
            Console.WriteLine(m2.Groups[0].Value);
            Console.WriteLine(m2.Groups.Count);//因为(?:123)不参与引用计数,所以m2.Groups.Count为 2
        }

        /// <summary>
        /// 匹配制定的位置
        /// </summary>
        static void Fun2()
        {
            Regex reg = new Regex("\\babc\\b");
            string str1 = "I am abc";
            string str2 = "I amabc";
            Console.WriteLine(reg.IsMatch(str1));
            Console.WriteLine(reg.IsMatch(str2));

            //下面这个例子在JS中无效
            Regex reg2 = new Regex("\\b你好\\b");
            string str3 = "中国 你好 黑";
            string str4 = "中国你好黑";
            Console.WriteLine(reg2.IsMatch(str3));
            Console.WriteLine(reg2.IsMatch(str4));
        }

        /// <summary>
        /// 正前向声明和反前向声明
        /// </summary>
        static void Fun3()
        {
            //正前向匹配,在[jJ]ava后者[jJ]ava[sS]cript后面一定要跟着冒号,但是匹配的值不包括冒号
            Regex reg = new Regex("[Jj]ava([Ss]cript)?(?=\\:)");
            string str = "Javascript: Good";
            Console.Write(reg.IsMatch(str) + "\t");
            Console.WriteLine(reg.Match(str).Value);//匹配的值为Javascript(没有包含冒号)

            Console.WriteLine(reg.IsMatch("Javascript : Good") + "\t");//不匹配,因为t和冒号之间还有一个空格           

            Console.Write(reg.IsMatch("Java:Good") + "\t");//匹配
            Console.WriteLine(reg.Match("Java:Good").Value);

            Console.WriteLine(reg.IsMatch("Java : Good") + "\t");//不匹配,因为a和冒号之间还有一个空格



            //反前向声明,在java后面跟任意字符,但是不能是script,且不区分大小写
            Regex reg2 = new Regex("Java(?!Script)(.*)", RegexOptions.IgnoreCase);
            Console.WriteLine(reg2.IsMatch("javascrip") + "\t" + reg2.Match("javascrip").Value);
            Console.WriteLine(reg2.IsMatch("Javascript is good") + "\t" + reg2.Match("Javascript").Value);

            Console.WriteLine(reg2.IsMatch("Java Script is good") + "\t" + reg2.Match("Java script is good").Value);

            //能在反前向声明中引用括号么
            Regex reg3 = new Regex("(['\"])hello[^\\1]");//本来想匹配的是 'hello再跟一个非'  或者 "hello再跟一个非" ,那么就与strEnd不匹配了 ,但是在字符类中使用括号引用是不合法的,所以居然还是匹配的
            string strEnd = "'hello'";
            string strEnd2 = "'hello\"";
            Console.WriteLine(reg3.IsMatch(strEnd));
            //那么我们在反前向声明中能使用括号引用么,看下面的代码
            Regex regEnd = new Regex("(['\"])hello(?!\\1)");
            Console.WriteLine(regEnd.IsMatch(strEnd));//匹配失败,说明在反前向声明中能使用括号引用
            Console.WriteLine(regEnd.IsMatch(strEnd2) + "\t" + regEnd.Match(strEnd2).Value);//匹配成功,但没有将 'hello后面的"也匹配出来
            Regex regEnd2 = new Regex("(['\"])hello(?!\\1).+");
            Console.WriteLine(regEnd2.IsMatch(strEnd2) + "\t" + regEnd2.Match(strEnd2).Value);//匹配成功,将 'hello后面的"也匹配出来
        }

        /// <summary>
        /// 回溯与非回溯
        /// </summary>
        static void Fun4()
        {
            #region 第一个例子
            string str = "www.csdn.net";
            Regex reg1 = new Regex(@"\w+\.(.*)\.\w+");
            Console.WriteLine(reg1.IsMatch(str));//匹配成功

            Regex reg2 = new Regex(@"\w+\.(?>.*)\.\w+");
            Console.WriteLine(reg2.IsMatch(str));//匹配失败

            /*
                "www.csdn.net" 可以通过@"\w+\.(.*)\.\w+"来匹配,却不能通过@"\w+\.(?>.*)\.\w+"来匹配!为什么呢?

原因是正则匹配是贪婪的,匹配时它会尽可能多的匹配最多的结果,所以,上例两个正则式中的.*都会把csdn.net匹配完, 这个时候,第一个表达式在开始匹配时发现\.\w+没得字符给它匹配了,所以它会进行回溯,所谓回溯,就是把.*匹配的结果往回推,回推留出来的字符再用来匹配\.\w+,直到\.\w+匹配成功,整个表达式返回成功的匹配结果。而第二个表达式,因使用的是非回溯匹配,所以,.*匹配完后,不允许通过回溯来匹配\.\w+,所以整个表达式匹配失败。

请注意,回溯匹配是很浪费资源的一种匹配方式,所以,请尽量避免您的正则式要通过回溯来成功匹配,如上例,可以换成@"\w+\.([^\.]+\.)+
             */
            #endregion

            #region 第二个例子
            string x = "Live for nothing,die for something";
            Regex r1 = new Regex(@".*thing,");
            if (r1.IsMatch(x))
            {
                Console.WriteLine("match:" + r1.Match(x).Value);//输出:Live for nothing,  
            }

            Regex r2 = new Regex(@"(?>.*)thing,");
            if (r2.IsMatch(x))//不匹配  
            {
                Console.WriteLine("match:" + r2.Match(x).Value);
            }
            else
            {
                Console.WriteLine("不匹配");
            }
            //在r1中,“.*”由于其贪婪特性,将一直匹配到字符串的最后,  
            //随后匹配“thing”,但在匹配“,”时失败,  
            //此时引擎将回溯,并在“thing,”处匹配成功。  
            //在r2中,由于强制非回溯,所以整个表达式匹配失败。
            #endregion
        }

        /// <summary>
        /// 不包含某个字串的两种方法
        /// </summary>
        static void Fun5()
        {
            #region 第一种
            string str = "Java script is good";
            string strP1 = "<p>Helo World</p>";
            string strP2 = "<p>你好<div>Realy</div></p>";
            //匹配一个字符串,这个字符串为以“java”开头,但是不能有“script”这个子串,使用这种方法有两点需要注意:
            //1.*必须放在大括号外面即不能写成((?!script).*),如果放在里面,则正则会将“ script”与“script”对比不相等也就匹配了(因为正是式贪婪的)
            //2.正则表达式的结尾有没有$会造成两种结果:(1)如果有$,那么凡是这个字符串中包括“script”这个子串,就找不到匹配的结果;(2)如果没有$,那么正则就会寻找遇到"script"之前后者之后有没有匹配,如果str为“Java script is good”(既在此例子中)会匹配“java ”,如果str为“script javasdf”则会匹配到“javasdf”
            Regex regMost = new Regex("java((?!script).)*$", RegexOptions.IgnoreCase);
            Match m = regMost.Match(str);
            Console.WriteLine(regMost.IsMatch(str));

            //那么如果我们想匹配一个字符串,而这个字符串中不能包含某一个子串,还想获得匹配的子串,例如我们想获取一个<p>标签里面的内容,而这个<p>标签里不能包含<div>标签

            //在((?!<div>).)* 外再加一个括号,就可以获取匹配的文本了
            Regex regP = new Regex("<p>(((?!<div>).)*)</p>");

            Match mp = regP.Match(strP1);
            //匹配成功
            if (mp.Success)
            {
                Console.WriteLine(mp.Groups[1].Value);
            }

            //匹配失败
            if (regP.IsMatch(strP2))
            {
            }
            else
            {
                Console.WriteLine("不匹配" + strP2);
            }
            #endregion

            #region 第二种
            //string myStr = "Java script is good";
            ////匹配一个以“java”开头的字符串,并且这个匹配的字符串中不能包含“script”
            //Regex myReg = new Regex("Java(?!.*script.*)", RegexOptions.IgnoreCase);
            //Match m2 = myReg.Match(myStr);
            //Console.WriteLine(m2.Success);

            ////Regex regL = new Regex("(<p>((?!<\\/p>).)*<\\/p>)|(<br\\/>)");

            Regex myReg2 = new Regex("<p>(?!.*<div>.*)(.*)</p>");
            Match myRes = myReg2.Match(strP1);
            if (myRes.Success)
            {
                Console.WriteLine(myRes.Groups[1].Value);
            }
            if (myReg2.IsMatch(strP2))
            {
            }
            else
            {
                Console.WriteLine("不匹配" + strP2);
            }
            #endregion
        }

        /// <summary>
        /// 永远不会匹配的正则
        /// </summary>
        static void Fun6()
        {
            Regex reg = new Regex("q(?=u)i");
            string s = "quit";
            //不匹配,因为正前向声明实际不消耗字符
            //Console.WriteLine(reg.IsMatch(s));

            //下面的正则能匹配,因为\d消耗了4
            Regex reg2 = new Regex("123(?=4)\\dabc");
            Console.WriteLine(reg2.IsMatch("1234abc"));
        }

        /// <summary>
        /// 向后查看
        /// </summary>
        static void Fun7()
        {
            string str = "abc123mm";
            //肯定式向后查看
            Regex reg = new Regex("(?<=123)mm");
            Console.WriteLine(reg.IsMatch(str));//匹配成功
            if (reg.IsMatch(str))
            {
                Console.WriteLine(reg.Match(str).Value);
            }
            Console.WriteLine(reg.IsMatch("23mm"));//匹配失败
            Console.WriteLine("--------------------------------------------------------");
            //否定式向后查看
            Regex reg2 = new Regex("(?<!123)mm");
            Console.WriteLine(reg2.IsMatch("abc123mm"));//匹配失败
            Console.WriteLine(reg2.IsMatch("abcmm"));//匹配成功
            Console.WriteLine(reg2.Match("abcmm").Value);
        }

        /// <summary>
        /// 单行模式和多行模式
        /// </summary>
        static void Fun8()
        {
            //1.默认既不是单行模式也不是多行模式            
            Console.WriteLine(Regex.IsMatch("a\nb", "a.{1}b"));// .不能匹配换行符
            //下面两个例子说明,既不是单行模式也不是多行模式的时候,^只能匹配字符串开头,$能匹配字符串结尾和行的结尾
            Console.WriteLine(Regex.IsMatch("a\nb", "^a\\nb$"));//^匹配字符串开头,$匹配字符串结尾
            Console.WriteLine(Regex.IsMatch("\nab", "^ab"));//^不能匹配行开头
            Console.WriteLine(Regex.IsMatch("ab\n", "ab$"));//$能匹配行结尾

            //单行模式
            Console.WriteLine(Regex.IsMatch("a\nb", "a.{1}b", RegexOptions.Singleline));// .能匹配换行符
            Console.WriteLine(Regex.IsMatch("a\nb", "^a.{1}b$", RegexOptions.Singleline));// ^匹配字符串开头,$能匹配字符串结尾
            Console.WriteLine(Regex.IsMatch("\nab", "^ab", RegexOptions.Singleline));// ^不能匹配行开头
            Console.WriteLine(Regex.IsMatch("ab\n", "ab$", RegexOptions.Singleline));// $能匹配行结尾

            //多行模式
            Console.WriteLine(Regex.IsMatch("a\nb", "a.{1}b", RegexOptions.Multiline));// .不能匹配换行符
            Console.WriteLine(Regex.IsMatch("ab", "^ab$", RegexOptions.Multiline));// ^匹配字符串开头,$能匹配字符串结尾
            Console.WriteLine(Regex.IsMatch("\nab", "^ab", RegexOptions.Multiline));// ^能匹配行开头
            Console.WriteLine(Regex.IsMatch("ab\n", "ab$", RegexOptions.Multiline));// $能匹配行结尾
            Console.WriteLine(Regex.IsMatch("\nab\n", "^ab$", RegexOptions.Multiline));// ^能匹配行开头,$能匹配行结尾
        }
    }
}
原文地址:https://www.cnblogs.com/mxw09/p/1784367.html