正则表达式:取第5个&和第6个&之间的字符串

时间:2022-11-20 18:49:33
如下功能怎么用正则表达式的方式实现?

int p5 = 0;
int p6 = 0;
int p = 0;

for (int i = 0; i < source.Length; i++)
{
    if (source[i] == '&')
    {
        p++;

        if (p == 5) p5 = i;
        else if (p == 6) p6 = i;
    }
}

if (p5 > 0 && p6 > 0)
    return source.Substring(p5 + 1, p6 - p5 - 1);
else return string.Empty;

47 个解决方案

#1


这样写挺好的。
正则不一定能更快。

#2



(?<=(.*?(?:&)){5})[^&]*

#3


[code=C#]string str = "&111&22&11&22&fsfs22&22&11&22&";
            Regex reg = new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);code]

#4


string str = "&111&22&11&22&fsfs22&22&11&22&";
            Regex reg = new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);

#5


召唤lxcnn吧,他是正则达人。不过还是少用正则的好,对于规则字符串查找,使用常规方法比正则更快。

#6


引用 2 楼 mbh0210 的回复:
C# code
(?<=(.*?(?:&)){5})[^&]*

看来mbh0210 的正则已经炉火纯青了啊
(?<YOurNeed>(?<=(.*?(?:&)){5})[^&]*)

#7


新手。。

#8


using System;
using System.Text.RegularExpressions;

class Test
{
  static void Main()
  {
    foreach (string s in new string[]{"abc", "&&1&&&123&.&.", "i&u"})
    {
      Console.WriteLine("{0}: [{1}]", s, Get5And6(s));
    }
  }
  
  // 取第5个&和第6个&之间的字符串
  static string Get5And6(string s)
  {
    return Regex.Match(s, @"(?s)(?:[^&]*&){5}([^&]*)&").Groups[1].Value;
  }
}
/* 程序输出:
abc: []
&&1&&&123&.&.: [123]
i&u: []
*/

#9


引用 1 楼 gomoku 的回复:
这样写挺好的。
 正则不一定能更快。


是吗?我不知道正则表达式的工作原理,一般正则表达式都很快,所以希望看看正则表达式的实现方式。

#10


从 LZ 提供的程序来看,对 "&&&&&NO6" 应该返回空字符串,2楼和6楼的都不符合 LZ 的原意。

#11


引用 2 楼 mbh0210 的回复:
C# code
(?<=(.*?(?:&)){5})[^&]*


这个写法很接近了,但是后续的&之间的之后的都被匹配到了

#12


8 楼的应该可以了:

return Regex.Match(s, @"(?:[^&]*&){5}([^&]*)&").Groups[1].Value;

#13


引用 4 楼 liherun 的回复:
C# codestring str="&111&22&11&22&fsfs22&22&11&22&";
            Regex reg=new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);


如果&有6个以上的话,这个写法会匹配到第6个和第7个之间的,第7第8之间的...

#14


学习

#15


(?:[^&]*&){5}([^&]*)

取Groups[1].Value

#16


恩?我没有那种情况

#17


或者这样写可以:
return Regex.Match(s, @"(?<=([^&]*&){5})[^&]*(?=&)").Value;

#18


3楼和4楼用 .* 是不妥的,如果字符串中有“换行符”,而 . 在默认情况下并不会匹配“换行符”,造成匹配失败。

#19


引用 12 楼 *8808 的回复:
8 楼的应该可以了:

C# codereturn Regex.Match(s,@"(?:[^&]*&){5}([^&]*)&").Groups[1].Value;


&&1&&&123&.&. 匹配结果: &&1&&&123&

#20


引用 11 楼 dongma_yifei 的回复:
引用 2 楼 mbh0210 的回复:
C# code
(? <=(.*?(?:&)){5})[^&]*


这个写法很接近了,但是后续的&之间的之后的都被匹配到了


试试这个,获取info

^.*?(?:&)(.*?(?:&)){4}(?<info>[^&]*)

#21


引用 19 楼 dongma_yifei 的回复:
引用 12 楼 *8808 的回复:
8 楼的应该可以了:

return Regex.Match(s,@"(?:[^&]*&){5}([^&]*)&").Groups[1].Value;


&&1&&&123&.&. 匹配结果: &&1&&&123&


我的程序运行结果是:

&&1&&&123&.&. 匹配结果:[123]

#22


注意 ,8楼的程序是:

return Regex.Match(s,@"(?:[^&]*&){5}([^&]*)&") .Groups[1].Value; 

#23


string str ="&&&111&22&33&123&&44&55&6662&7771&888888&"; 
            Regex reg = new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);

得到的是33

#24


LZ,请注意 8 楼和 17 楼的区别,8 楼的有  .Groups[1] ,17 楼的没有。

#25


引用 23 楼 liherun 的回复:
string str="&&&111&22&33&123&&44&55&6662&7771&888888&"; 
            Regex reg=new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);
得到的是33


如果是:
string str = "&& \n&111&22&33&123&&44&55&6662&7771&888888&"; 

那么,用 .* 就不正确了。

#26


恩恩,谢谢空军老大

#27


我认为,8楼和17楼的正则都符合LZ的题意。

#28


谢谢各位的回答,回头我研究下再散分
毕竟 (? ) 这种方式非高手是写不出来的,理解起来也难

#29


空军大哥的正则是牛啊
膜拜

#30


正则的算法大家有不有深入了解过啊,
可能是微软把算法封在Regex 类中了,
它只是看起来代码短一点而以,让我们省了很多事,
执行效力应该快不到哪去

#31


c语言还不会怎么办

#32


这样写挺好的。 
正则不一定能更快。

#33



以上都不太好
这个

"(?n)(?<=^([^&]*&){5})[^&]*"  
// 注意有个^表示开始的标志位才行,要不就会将第5第6之间的第6第7等等匹配出来。
// 因为(?<=exp)是零消耗的会从头开始一个一个字符的匹配整个正则 找到匹配的。


#34


修改一下  不足六个 不匹配

"(?n)(?<=^([^&]*&){5})[^&]*(?=&)"

另外

"(?n)^([^&]*&){5}(?<value>[^&]*)&"



"(?sn)^(.*?&){5}(?<value>.*?)&"


以上都可以  但要有 ^ 在开头

#35


引用 34 楼 wackyboy 的回复:
但要有 ^ 在开头


没有必要。默认的情形,正则就是从字符串的第一个字符开始匹配的。


对于 LZ 的题目,8楼和17楼的正则都能很好地工作,不存在匹配到第6、7个之类的问题。

#36


因为:
return Regex.Match(s, @"(?<=([^&]*&){5})[^&]*(?=&)").Value;

这是返回第一个匹配(如果存在匹配的话),所以没有加  ^ 也不会匹配到6、7个之间。

又没有调用 NextMatch(),所以不存在  wackyboy 说的问题,你的担心是没有必要的。

#37


引用 5 楼 qldsrx 的回复:
召唤lxcnn吧,他是正则达人。不过还是少用正则的好,对于规则字符串查找,使用常规方法比正则更快。


如果这个对效率要求较高,那么肯定是自己写状态机效率高的,楼主的方法用StringBuilder改进一下就是了

如果非要用正则,8楼、17楼、34楼的都可以,最近工作太忙,大脑有些秀逗,不太适合回答问题

#38


引用 36 楼 *8808 的回复:
又没有调用 NextMatch(),所以不存在wackyboy 说的问题,你的担心是没有必要的。


在整个源字符串匹配成功的情况下,加不加“^”没什么区别,在整个源字符串匹配不成功的情况下,wackyboy 的考虑还是有必要的

#39


引用 38 楼 lxcnn 的回复:
在整个源字符串匹配不成功的情况下,wackyboy 的考虑还是有必要的


在整个源字符串匹配不成功的情况下,会直接  return 一个空字符串,wackyboy 的考虑还是有必要吗?

#40


我认为,就 LZ 这个题目而言,加 ^ 是没有必要的, 过客你认为呢?

#41


我理解 过客的意思是说: 在整个源字符串匹配不成功的情况下,加 ^ 可以尽早促使匹配失败,返回空字符串,以提高效率。

我的理解对吗?

#42


引用 37 楼 lxcnn 的回复:
引用 5 楼 qldsrx 的回复:
 召唤lxcnn吧,他是正则达人。不过还是少用正则的好,对于规则字符串查找,使用常规方法比正则更快。


 如果这个对效率要求较高,那么肯定是自己写状态机效率高的,楼主的方法用StringBuilder改进一下就是了

 如果非要用正则,8楼、17楼、34楼的都可以,最近工作太忙,大脑有些秀逗,不太适合回答问题


汗!我只用了substring,又没有用字符串相加,stringbuilder怎么帮我改进?
难道你是说找到第5个&后设置标志,直到第6个&前的字符每个都加起来吗?这样比substring效率会高吗?我确实不知道。
(ps:突然发现我的代码确实有应该改进的地方,很明显少了一个break)

#43


引用 41 楼 *8808 的回复:
我理解过客的意思是说:在整个源字符串匹配不成功的情况下,加 ^ 可以尽早促使匹配失败,返回空字符串,以提高效率。

我的理解对吗?


是的,是这个意思,为了尽早的报告匹配失败
现在绝大多数正则引擎都对“^”做了优化的,只要在位置0处匹配失败,就不会再尝试匹配其它位置了

#44


引用 42 楼 dongma_yifei 的回复:
汗!我只用了substring,又没有用字符串相加,stringbuilder怎么帮我改进?
难道你是说找到第5个&后设置标志,直到第6个&前的字符每个都加起来吗?这样比substring效率会高吗?我确实不知道。
(ps:突然发现我的代码确实有应该改进的地方,很明显少了一个break)


不用Substring,这样的效率低
不过如果涉及到效率,那可能要考虑算法了,这个要找*8808了,*8808是算法高手

#45


这个题目并没有涉及到什么高深的算法,
效率方面可能是最主要的因素

#46


恩  我错了  
请楼主忽略 33楼 34楼的答案

#47


string str = "&111&22&11&22&fsfs22&22&11&22&"; 
Regex reg = new Regex("(?:[^&]*&){5}(?<value>[^&]*)&");
Match m = reg.Match(str);
if(m.Success) 
{
    MessageBox.Show("获取的字符串是:"+reg.Groups["value"].Value);
}
else
    MessageBox.Show("字符串中没有包含6个以上的&字符");

#1


这样写挺好的。
正则不一定能更快。

#2



(?<=(.*?(?:&)){5})[^&]*

#3


[code=C#]string str = "&111&22&11&22&fsfs22&22&11&22&";
            Regex reg = new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);code]

#4


string str = "&111&22&11&22&fsfs22&22&11&22&";
            Regex reg = new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);

#5


召唤lxcnn吧,他是正则达人。不过还是少用正则的好,对于规则字符串查找,使用常规方法比正则更快。

#6


引用 2 楼 mbh0210 的回复:
C# code
(?<=(.*?(?:&)){5})[^&]*

看来mbh0210 的正则已经炉火纯青了啊
(?<YOurNeed>(?<=(.*?(?:&)){5})[^&]*)

#7


新手。。

#8


using System;
using System.Text.RegularExpressions;

class Test
{
  static void Main()
  {
    foreach (string s in new string[]{"abc", "&&1&&&123&.&.", "i&u"})
    {
      Console.WriteLine("{0}: [{1}]", s, Get5And6(s));
    }
  }
  
  // 取第5个&和第6个&之间的字符串
  static string Get5And6(string s)
  {
    return Regex.Match(s, @"(?s)(?:[^&]*&){5}([^&]*)&").Groups[1].Value;
  }
}
/* 程序输出:
abc: []
&&1&&&123&.&.: [123]
i&u: []
*/

#9


引用 1 楼 gomoku 的回复:
这样写挺好的。
 正则不一定能更快。


是吗?我不知道正则表达式的工作原理,一般正则表达式都很快,所以希望看看正则表达式的实现方式。

#10


从 LZ 提供的程序来看,对 "&&&&&NO6" 应该返回空字符串,2楼和6楼的都不符合 LZ 的原意。

#11


引用 2 楼 mbh0210 的回复:
C# code
(?<=(.*?(?:&)){5})[^&]*


这个写法很接近了,但是后续的&之间的之后的都被匹配到了

#12


8 楼的应该可以了:

return Regex.Match(s, @"(?:[^&]*&){5}([^&]*)&").Groups[1].Value;

#13


引用 4 楼 liherun 的回复:
C# codestring str="&111&22&11&22&fsfs22&22&11&22&";
            Regex reg=new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);


如果&有6个以上的话,这个写法会匹配到第6个和第7个之间的,第7第8之间的...

#14


学习

#15


(?:[^&]*&){5}([^&]*)

取Groups[1].Value

#16


恩?我没有那种情况

#17


或者这样写可以:
return Regex.Match(s, @"(?<=([^&]*&){5})[^&]*(?=&)").Value;

#18


3楼和4楼用 .* 是不妥的,如果字符串中有“换行符”,而 . 在默认情况下并不会匹配“换行符”,造成匹配失败。

#19


引用 12 楼 *8808 的回复:
8 楼的应该可以了:

C# codereturn Regex.Match(s,@"(?:[^&]*&){5}([^&]*)&").Groups[1].Value;


&&1&&&123&.&. 匹配结果: &&1&&&123&

#20


引用 11 楼 dongma_yifei 的回复:
引用 2 楼 mbh0210 的回复:
C# code
(? <=(.*?(?:&)){5})[^&]*


这个写法很接近了,但是后续的&之间的之后的都被匹配到了


试试这个,获取info

^.*?(?:&)(.*?(?:&)){4}(?<info>[^&]*)

#21


引用 19 楼 dongma_yifei 的回复:
引用 12 楼 *8808 的回复:
8 楼的应该可以了:

return Regex.Match(s,@"(?:[^&]*&){5}([^&]*)&").Groups[1].Value;


&&1&&&123&.&. 匹配结果: &&1&&&123&


我的程序运行结果是:

&&1&&&123&.&. 匹配结果:[123]

#22


注意 ,8楼的程序是:

return Regex.Match(s,@"(?:[^&]*&){5}([^&]*)&") .Groups[1].Value; 

#23


string str ="&&&111&22&33&123&&44&55&6662&7771&888888&"; 
            Regex reg = new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);

得到的是33

#24


LZ,请注意 8 楼和 17 楼的区别,8 楼的有  .Groups[1] ,17 楼的没有。

#25


引用 23 楼 liherun 的回复:
string str="&&&111&22&33&123&&44&55&6662&7771&888888&"; 
            Regex reg=new Regex(@"(?<=(?:.*&){5}).*?(?=&)");
            MessageBox.Show(reg.Match(str).Value);
得到的是33


如果是:
string str = "&& \n&111&22&33&123&&44&55&6662&7771&888888&"; 

那么,用 .* 就不正确了。

#26


恩恩,谢谢空军老大

#27


我认为,8楼和17楼的正则都符合LZ的题意。

#28


谢谢各位的回答,回头我研究下再散分
毕竟 (? ) 这种方式非高手是写不出来的,理解起来也难

#29


空军大哥的正则是牛啊
膜拜

#30


正则的算法大家有不有深入了解过啊,
可能是微软把算法封在Regex 类中了,
它只是看起来代码短一点而以,让我们省了很多事,
执行效力应该快不到哪去

#31


c语言还不会怎么办

#32


这样写挺好的。 
正则不一定能更快。

#33



以上都不太好
这个

"(?n)(?<=^([^&]*&){5})[^&]*"  
// 注意有个^表示开始的标志位才行,要不就会将第5第6之间的第6第7等等匹配出来。
// 因为(?<=exp)是零消耗的会从头开始一个一个字符的匹配整个正则 找到匹配的。


#34


修改一下  不足六个 不匹配

"(?n)(?<=^([^&]*&){5})[^&]*(?=&)"

另外

"(?n)^([^&]*&){5}(?<value>[^&]*)&"



"(?sn)^(.*?&){5}(?<value>.*?)&"


以上都可以  但要有 ^ 在开头

#35


引用 34 楼 wackyboy 的回复:
但要有 ^ 在开头


没有必要。默认的情形,正则就是从字符串的第一个字符开始匹配的。


对于 LZ 的题目,8楼和17楼的正则都能很好地工作,不存在匹配到第6、7个之类的问题。

#36


因为:
return Regex.Match(s, @"(?<=([^&]*&){5})[^&]*(?=&)").Value;

这是返回第一个匹配(如果存在匹配的话),所以没有加  ^ 也不会匹配到6、7个之间。

又没有调用 NextMatch(),所以不存在  wackyboy 说的问题,你的担心是没有必要的。

#37


引用 5 楼 qldsrx 的回复:
召唤lxcnn吧,他是正则达人。不过还是少用正则的好,对于规则字符串查找,使用常规方法比正则更快。


如果这个对效率要求较高,那么肯定是自己写状态机效率高的,楼主的方法用StringBuilder改进一下就是了

如果非要用正则,8楼、17楼、34楼的都可以,最近工作太忙,大脑有些秀逗,不太适合回答问题

#38


引用 36 楼 *8808 的回复:
又没有调用 NextMatch(),所以不存在wackyboy 说的问题,你的担心是没有必要的。


在整个源字符串匹配成功的情况下,加不加“^”没什么区别,在整个源字符串匹配不成功的情况下,wackyboy 的考虑还是有必要的

#39


引用 38 楼 lxcnn 的回复:
在整个源字符串匹配不成功的情况下,wackyboy 的考虑还是有必要的


在整个源字符串匹配不成功的情况下,会直接  return 一个空字符串,wackyboy 的考虑还是有必要吗?

#40


我认为,就 LZ 这个题目而言,加 ^ 是没有必要的, 过客你认为呢?

#41


我理解 过客的意思是说: 在整个源字符串匹配不成功的情况下,加 ^ 可以尽早促使匹配失败,返回空字符串,以提高效率。

我的理解对吗?

#42


引用 37 楼 lxcnn 的回复:
引用 5 楼 qldsrx 的回复:
 召唤lxcnn吧,他是正则达人。不过还是少用正则的好,对于规则字符串查找,使用常规方法比正则更快。


 如果这个对效率要求较高,那么肯定是自己写状态机效率高的,楼主的方法用StringBuilder改进一下就是了

 如果非要用正则,8楼、17楼、34楼的都可以,最近工作太忙,大脑有些秀逗,不太适合回答问题


汗!我只用了substring,又没有用字符串相加,stringbuilder怎么帮我改进?
难道你是说找到第5个&后设置标志,直到第6个&前的字符每个都加起来吗?这样比substring效率会高吗?我确实不知道。
(ps:突然发现我的代码确实有应该改进的地方,很明显少了一个break)

#43


引用 41 楼 *8808 的回复:
我理解过客的意思是说:在整个源字符串匹配不成功的情况下,加 ^ 可以尽早促使匹配失败,返回空字符串,以提高效率。

我的理解对吗?


是的,是这个意思,为了尽早的报告匹配失败
现在绝大多数正则引擎都对“^”做了优化的,只要在位置0处匹配失败,就不会再尝试匹配其它位置了

#44


引用 42 楼 dongma_yifei 的回复:
汗!我只用了substring,又没有用字符串相加,stringbuilder怎么帮我改进?
难道你是说找到第5个&后设置标志,直到第6个&前的字符每个都加起来吗?这样比substring效率会高吗?我确实不知道。
(ps:突然发现我的代码确实有应该改进的地方,很明显少了一个break)


不用Substring,这样的效率低
不过如果涉及到效率,那可能要考虑算法了,这个要找*8808了,*8808是算法高手

#45


这个题目并没有涉及到什么高深的算法,
效率方面可能是最主要的因素

#46


恩  我错了  
请楼主忽略 33楼 34楼的答案

#47


string str = "&111&22&11&22&fsfs22&22&11&22&"; 
Regex reg = new Regex("(?:[^&]*&){5}(?<value>[^&]*)&");
Match m = reg.Match(str);
if(m.Success) 
{
    MessageBox.Show("获取的字符串是:"+reg.Groups["value"].Value);
}
else
    MessageBox.Show("字符串中没有包含6个以上的&字符");