【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

时间:2023-01-03 13:17:28
    题目要求:将"我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...",变成"我爱你"。

    我个人代码如下所示:

string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
 //Regex.Replace(msg, @"");
 string[] strNum = Regex.Split(msg, @"\.", RegexOptions.IgnorePatternWhitespace);
 //Console.WriteLine(strNum);
string msg2 = null;
for (int i = 0; i < strNum.Length; i++)
{
      msg2 += strNum;
 }

  msg2 = Regex.Replace(msg, @"(.)\1+", "$1");

 Console.WriteLine(msg2);

Console.ReadKey();




我个人在编写运行我自己的代码时遇到的问题:

       在代码运行完下面一行代码(局部代码一)后,strNum数组中就没有‘.’(点号)了,如图片1所示。

局部代码一
 string[] strNum = Regex.Split(msg, @"\.", RegexOptions.IgnorePatternWhitespace);

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

图片1


       取一空字符串msg,遍历字符串数组strNum,使strNum字符串数组中的每个元素都赋值给msg。我很奇怪的时,当将strNum数组中的每个字符赋值给msg后,msg中的内容为:我我我我我我我爱爱爱爱爱你你你你你你 ,如图片2所示。为何当msg运行下一行代码(局部代码二)后,就变成了:我.我.我.爱.爱.爱.你.你.你. ?如图片3所示。

局部代码二

msg2 = Regex.Replace(msg, @"(.)\1+", "$1");


【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

图片2


【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

图片3


    这个是怎么回事?求指点,谢谢。   


         [i] 在最后分享一首我曾经分享过的诗




*与情 两首

金庸 [现代]

千古垂名有何欢,世人谁知帝王难。

一个情字书万卷,只写恩爱是*。

女人本是一枝花,花开四季原为他。

宁愿情郎捻成土,也不开在富贵家。



          我美丽的校园

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割




18 个解决方案

#1


本则帖子中引用的《*与情 两首》,是金庸武侠小说《侠客行》中的一首古诗。

《侠客行》本部小说,在87、2001被翻拍成电视剧。2001年翻拍的电视剧有些不清晰,不过剧情还是挺丰富的。在剧中,各类武林人物交手搏斗场面不可胜数,但历历写来,景随情转,变化无穷而皆能贴合生活,让你如同身临其境。

希望能够得到各位前辈、小伙伴的指点,帮我解决本帖中遇到的问题。 【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#2


变量写错了
29行的msg应该为msg2

#3


按说Regex支持反向引用,可以只用一趟替换。
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = @"(?<c>[^.])\.*(\k<c>\.*)*";
    string result = Regex.Replace(msg, pattern, "${c}");
}

注释版:
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = 
        @"
            (?<c>           # 开启捕获组,名字叫c
                [^.]        #   匹配除'.'以外的任何一个字符
            )               # 结束捕获组
            \.*             # 任意个的'.'
            (               # 开启捕获组
                \k<c>       #   匹配上一个名字叫c的捕获组
                \.*         #   任意个的'.' 
            )*              # 结束捕获组,并允许该组任意重复
        ";
    string result = new Regex(pattern, RegexOptions.IgnorePatternWhitespace).Replace(msg, "${c}");
}


#4


引用 2 楼 stherix 的回复:
变量写错了
29行的msg应该为msg2


嗯,是的,错误就在这里。谢谢

我想知道,你是如何发现这个错误的?我当时就一直不明白是怎么回事!我仔细想了一想自己的解题思路,思路无误,代码也无“错误”。当时,就是不知道第29行的msg应该改成msg2 。  这个msg我当时考虑的是msg2,但是可能敲代码时,一下敲成了msg!

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割







#5


仅供参考:
//有字符串
//1_22_333,,4444__55555,_666666
//需要解析为
//1
//22
//333
//_
//4444
//55555
//666666
#include <stdio.h>
char s[]="1_22_333,,4444__55555,_666666";
char c,*p,*p1;
int st;
void main() {
    st=0;
    p=s;
    while (1) {
        c=*p;
        if (0==c) {
            switch (st) {
            case 1:printf("_\n");    break;
            case 2:printf("%s\n",p1);break;
            }
            break;//
        }
        switch (st) {
        case 0:
                 if ('_'==c) {                            st=0;}
            else if (','==c) {                            st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 1:
                 if ('_'==c) {                            st=1;}
            else if (','==c) {printf("_\n");              st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 2:
                 if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}
            else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}
            else             {                            st=2;}
        break;
        }
        p++;
    }
}
//1
//22
//333
//_
//4444
//55555
//666666

提醒:正则表达式不是万能的;而有限状态自动机是万能的。

#6


引用 3 楼 Forty2 的回复:
按说Regex支持反向引用,可以只用一趟替换。
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = @"(?<c>[^.])\.*(\k<c>\.*)*";
    string result = Regex.Replace(msg, pattern, "${c}");
}

注释版:
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = 
        @"
            (?<c>           # 开启捕获组,名字叫c
                [^.]        #   匹配除'.'以外的任何一个字符
            )               # 结束捕获组
            \.*             # 任意个的'.'
            (               # 开启捕获组
                \k<c>       #   匹配上一个名字叫c的捕获组
                \.*         #   任意个的'.' 
            )*              # 结束捕获组,并允许该组任意重复
        ";
    string result = new Regex(pattern, RegexOptions.IgnorePatternWhitespace).Replace(msg, "${c}");
}


谢谢您的回复。

前辈对于正则表达式的研究很深入啊,你写的正则表达式有些地方我都看不懂。

我本帖中的问题,第二层的网友已经给出了答案。谢谢你们

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#7


引用 5 楼 zhao4zhong1 的回复:
仅供参考:
//有字符串
//1_22_333,,4444__55555,_666666
//需要解析为
//1
//22
//333
//_
//4444
//55555
//666666
#include <stdio.h>
char s[]="1_22_333,,4444__55555,_666666";
char c,*p,*p1;
int st;
void main() {
    st=0;
    p=s;
    while (1) {
        c=*p;
        if (0==c) {
            switch (st) {
            case 1:printf("_\n");    break;
            case 2:printf("%s\n",p1);break;
            }
            break;//
        }
        switch (st) {
        case 0:
                 if ('_'==c) {                            st=0;}
            else if (','==c) {                            st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 1:
                 if ('_'==c) {                            st=1;}
            else if (','==c) {printf("_\n");              st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 2:
                 if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}
            else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}
            else             {                            st=2;}
        break;
        }
        p++;
    }
}
//1
//22
//333
//_
//4444
//55555
//666666

提醒:正则表达式不是万能的;而有限状态自动机是万能的。


嗯,谢谢赵老师的指点。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#8


不信的话,让谁用正则表达式解这道题。

#9


参考《编译原理》中的词法分析和有限状态自动机。

#10


引用 9 楼 zhao4zhong1 的回复:
参考《编译原理》中的词法分析和有限状态自动机。


《编译原理》目前刚刚学到有限自动机、无限自动机。但是,感觉没啥用。而且,这个地方,也不好学。知识点有些绕。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#11


引用 10 楼 dear_Alice_moon 的回复:
Quote: 引用 9 楼 zhao4zhong1 的回复:

参考《编译原理》中的词法分析和有限状态自动机。


《编译原理》目前刚刚学到有限自动机、无限自动机。但是,感觉没啥用。而且,这个地方,也不好学。知识点有些绕。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割


其实回想我数十年的IT生涯,《编译原理》这门课中N多知识点中也就“使用有限状态自动机做词法分析”在后来的实际工作中应用过。

#12


要会画状态转换图。

#13


引用 12 楼 zhao4zhong1 的回复:
要会画状态转换图。


嗯,我会记得赵老师你的这个指点的。我个人也挺喜欢绘图的。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#14


string.Join("", Regex.Matches("我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...", @"[\u4e00-\u9fa5]").Cast<Match>().Select(m => m.Value).Distinct())

#15


正则也是 有限状态自动机

#16


引用 4 楼 dear_Alice_moon 的回复:
Quote: 引用 2 楼 stherix 的回复:

变量写错了
29行的msg应该为msg2


嗯,是的,错误就在这里。谢谢

我想知道,你是如何发现这个错误的?我当时就一直不明白是怎么回事!我仔细想了一想自己的解题思路,思路无误,代码也无“错误”。当时,就是不知道第29行的msg应该改成msg2 。  这个msg我当时考虑的是msg2,但是可能敲代码时,一下敲成了msg!




很容易想到把
明明已经通过split把句点全部去掉了,最后的替换结果里面居然还有句点
要么是split语句有问题,要么就是引用了不正确的中间变量了

#17


引用 16 楼 stherix 的回复:
Quote: 引用 4 楼 dear_Alice_moon 的回复:

Quote: 引用 2 楼 stherix 的回复:

变量写错了
29行的msg应该为msg2


嗯,是的,错误就在这里。谢谢

我想知道,你是如何发现这个错误的?我当时就一直不明白是怎么回事!我仔细想了一想自己的解题思路,思路无误,代码也无“错误”。当时,就是不知道第29行的msg应该改成msg2 。  这个msg我当时考虑的是msg2,但是可能敲代码时,一下敲成了msg!



很容易想到把
明明已经通过split把句点全部去掉了,最后的替换结果里面居然还有句点
要么是split语句有问题,要么就是引用了不正确的中间变量了


哦,是这样啊。谢谢

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#18


引用 15 楼 xuzuning 的回复:
正则也是 有限状态自动机

谬论。不然你试试用正则解一下5楼的题。

#1


本则帖子中引用的《*与情 两首》,是金庸武侠小说《侠客行》中的一首古诗。

《侠客行》本部小说,在87、2001被翻拍成电视剧。2001年翻拍的电视剧有些不清晰,不过剧情还是挺丰富的。在剧中,各类武林人物交手搏斗场面不可胜数,但历历写来,景随情转,变化无穷而皆能贴合生活,让你如同身临其境。

希望能够得到各位前辈、小伙伴的指点,帮我解决本帖中遇到的问题。 【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#2


变量写错了
29行的msg应该为msg2

#3


按说Regex支持反向引用,可以只用一趟替换。
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = @"(?<c>[^.])\.*(\k<c>\.*)*";
    string result = Regex.Replace(msg, pattern, "${c}");
}

注释版:
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = 
        @"
            (?<c>           # 开启捕获组,名字叫c
                [^.]        #   匹配除'.'以外的任何一个字符
            )               # 结束捕获组
            \.*             # 任意个的'.'
            (               # 开启捕获组
                \k<c>       #   匹配上一个名字叫c的捕获组
                \.*         #   任意个的'.' 
            )*              # 结束捕获组,并允许该组任意重复
        ";
    string result = new Regex(pattern, RegexOptions.IgnorePatternWhitespace).Replace(msg, "${c}");
}


#4


引用 2 楼 stherix 的回复:
变量写错了
29行的msg应该为msg2


嗯,是的,错误就在这里。谢谢

我想知道,你是如何发现这个错误的?我当时就一直不明白是怎么回事!我仔细想了一想自己的解题思路,思路无误,代码也无“错误”。当时,就是不知道第29行的msg应该改成msg2 。  这个msg我当时考虑的是msg2,但是可能敲代码时,一下敲成了msg!

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割







#5


仅供参考:
//有字符串
//1_22_333,,4444__55555,_666666
//需要解析为
//1
//22
//333
//_
//4444
//55555
//666666
#include <stdio.h>
char s[]="1_22_333,,4444__55555,_666666";
char c,*p,*p1;
int st;
void main() {
    st=0;
    p=s;
    while (1) {
        c=*p;
        if (0==c) {
            switch (st) {
            case 1:printf("_\n");    break;
            case 2:printf("%s\n",p1);break;
            }
            break;//
        }
        switch (st) {
        case 0:
                 if ('_'==c) {                            st=0;}
            else if (','==c) {                            st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 1:
                 if ('_'==c) {                            st=1;}
            else if (','==c) {printf("_\n");              st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 2:
                 if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}
            else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}
            else             {                            st=2;}
        break;
        }
        p++;
    }
}
//1
//22
//333
//_
//4444
//55555
//666666

提醒:正则表达式不是万能的;而有限状态自动机是万能的。

#6


引用 3 楼 Forty2 的回复:
按说Regex支持反向引用,可以只用一趟替换。
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = @"(?<c>[^.])\.*(\k<c>\.*)*";
    string result = Regex.Replace(msg, pattern, "${c}");
}

注释版:
static void Main()
{
    string msg = "我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...";
    string pattern = 
        @"
            (?<c>           # 开启捕获组,名字叫c
                [^.]        #   匹配除'.'以外的任何一个字符
            )               # 结束捕获组
            \.*             # 任意个的'.'
            (               # 开启捕获组
                \k<c>       #   匹配上一个名字叫c的捕获组
                \.*         #   任意个的'.' 
            )*              # 结束捕获组,并允许该组任意重复
        ";
    string result = new Regex(pattern, RegexOptions.IgnorePatternWhitespace).Replace(msg, "${c}");
}


谢谢您的回复。

前辈对于正则表达式的研究很深入啊,你写的正则表达式有些地方我都看不懂。

我本帖中的问题,第二层的网友已经给出了答案。谢谢你们

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#7


引用 5 楼 zhao4zhong1 的回复:
仅供参考:
//有字符串
//1_22_333,,4444__55555,_666666
//需要解析为
//1
//22
//333
//_
//4444
//55555
//666666
#include <stdio.h>
char s[]="1_22_333,,4444__55555,_666666";
char c,*p,*p1;
int st;
void main() {
    st=0;
    p=s;
    while (1) {
        c=*p;
        if (0==c) {
            switch (st) {
            case 1:printf("_\n");    break;
            case 2:printf("%s\n",p1);break;
            }
            break;//
        }
        switch (st) {
        case 0:
                 if ('_'==c) {                            st=0;}
            else if (','==c) {                            st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 1:
                 if ('_'==c) {                            st=1;}
            else if (','==c) {printf("_\n");              st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 2:
                 if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}
            else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}
            else             {                            st=2;}
        break;
        }
        p++;
    }
}
//1
//22
//333
//_
//4444
//55555
//666666

提醒:正则表达式不是万能的;而有限状态自动机是万能的。


嗯,谢谢赵老师的指点。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#8


不信的话,让谁用正则表达式解这道题。

#9


参考《编译原理》中的词法分析和有限状态自动机。

#10


引用 9 楼 zhao4zhong1 的回复:
参考《编译原理》中的词法分析和有限状态自动机。


《编译原理》目前刚刚学到有限自动机、无限自动机。但是,感觉没啥用。而且,这个地方,也不好学。知识点有些绕。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#11


引用 10 楼 dear_Alice_moon 的回复:
Quote: 引用 9 楼 zhao4zhong1 的回复:

参考《编译原理》中的词法分析和有限状态自动机。


《编译原理》目前刚刚学到有限自动机、无限自动机。但是,感觉没啥用。而且,这个地方,也不好学。知识点有些绕。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割


其实回想我数十年的IT生涯,《编译原理》这门课中N多知识点中也就“使用有限状态自动机做词法分析”在后来的实际工作中应用过。

#12


要会画状态转换图。

#13


引用 12 楼 zhao4zhong1 的回复:
要会画状态转换图。


嗯,我会记得赵老师你的这个指点的。我个人也挺喜欢绘图的。

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#14


string.Join("", Regex.Matches("我...我我..我我我我....爱爱爱..爱..爱...你你...你..你你你...", @"[\u4e00-\u9fa5]").Cast<Match>().Select(m => m.Value).Distinct())

#15


正则也是 有限状态自动机

#16


引用 4 楼 dear_Alice_moon 的回复:
Quote: 引用 2 楼 stherix 的回复:

变量写错了
29行的msg应该为msg2


嗯,是的,错误就在这里。谢谢

我想知道,你是如何发现这个错误的?我当时就一直不明白是怎么回事!我仔细想了一想自己的解题思路,思路无误,代码也无“错误”。当时,就是不知道第29行的msg应该改成msg2 。  这个msg我当时考虑的是msg2,但是可能敲代码时,一下敲成了msg!




很容易想到把
明明已经通过split把句点全部去掉了,最后的替换结果里面居然还有句点
要么是split语句有问题,要么就是引用了不正确的中间变量了

#17


引用 16 楼 stherix 的回复:
Quote: 引用 4 楼 dear_Alice_moon 的回复:

Quote: 引用 2 楼 stherix 的回复:

变量写错了
29行的msg应该为msg2


嗯,是的,错误就在这里。谢谢

我想知道,你是如何发现这个错误的?我当时就一直不明白是怎么回事!我仔细想了一想自己的解题思路,思路无误,代码也无“错误”。当时,就是不知道第29行的msg应该改成msg2 。  这个msg我当时考虑的是msg2,但是可能敲代码时,一下敲成了msg!



很容易想到把
明明已经通过split把句点全部去掉了,最后的替换结果里面居然还有句点
要么是split语句有问题,要么就是引用了不正确的中间变量了


哦,是这样啊。谢谢

【话题:学习交流】C#中字符串的正则表达式之反向引用、分割

#18


引用 15 楼 xuzuning 的回复:
正则也是 有限状态自动机

谬论。不然你试试用正则解一下5楼的题。