Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用正则表达式从字符串中提取数字组_C#_.net_Regex - Fatal编程技术网

C# 使用正则表达式从字符串中提取数字组

C# 使用正则表达式从字符串中提取数字组,c#,.net,regex,C#,.net,Regex,我需要转换一个字符串,比如 "[1,2,3,4][5,6,7,8]" 分成整数组,调整为零基而不是一基: {0,1,2,3} {4,5,6,7} 下列规则也适用: 字符串必须至少包含一组带方括号的数字 每组必须至少包含2个数字 每个数字都必须是唯一的(这不是我试图用正则表达式实现的) 0无效,但10100等无效 因为我对正则表达式没有太多经验,所以我现在使用两个 @"^(?:\[(?:[1-9]+[\d]*,)+(?:[1-9]+[\d]*){1}\])+$"; 及 我使用第一个来检查

我需要转换一个字符串,比如

"[1,2,3,4][5,6,7,8]"
分成整数组,调整为零基而不是一基:

{0,1,2,3} {4,5,6,7}
下列规则也适用:

  • 字符串必须至少包含一组带方括号的数字
  • 每组必须至少包含2个数字
  • 每个数字都必须是唯一的(这不是我试图用正则表达式实现的)
  • 0无效,但10100等无效
因为我对正则表达式没有太多经验,所以我现在使用两个

@"^(?:\[(?:[1-9]+[\d]*,)+(?:[1-9]+[\d]*){1}\])+$";

我使用第一个来检查输入,第二个来获取方括号内一组数字的所有匹配项

然后,我使用.Net字符串操作修剪方括号并提取数字,解析它们并减去1以得到我需要的结果

我想知道是否可以通过使用捕获来更好地获取数字,但不确定它们是如何工作的


最终解决方案:

最后,我使用以下正则表达式来验证输入字符串

@"^(?<set>\[(?:[1-9]\d{0,7}(?:]|,(?=\d))){2,})+$"
@“^(?\[(?:[1-9]\d{0,7}(?:]|,(?=\d)){2,}+$”
agent-j的模式可以捕获所需的信息,但也可以匹配“[1,2,3,4][5]”之类的字符串,并且需要我对结果进行一些额外的过滤

我通过命名组“set”访问捕获,并使用第二个简单的正则表达式提取数字

“[1-9]\d{0,7}”通过将数字限制为99999999并避免溢出异常,简化了对int的解析

MatchCollection matches = new Regex(@"^(?<set>\[(?:[1-9]\d{0,7}(?:]|,(?=\d))){2,})+$").Matches(inputText);

if (matches.Count != 1)return;

CaptureCollection captures = matches[0].Groups["set"].Captures;

var resultJArray = new int[captures.Count][];
var numbersRegex =  new Regex(@"\d+");
for (int captureIndex = 0; captureIndex < captures.Count; captureIndex++)
{
    string capture = captures[captureIndex].Value;
    MatchCollection numberMatches = numbersRegex.Matches(capture);
    resultJArray [captureIndex] = new int[numberMatches.Count];
    for (int numberMatchIndex = 0; numberMatchIndex < numberMatches.Count; numberMatchIndex++)
    {
        string number = numberMatches[numberMatchIndex].Value;
        int numberAdjustedToZeroBase = Int32.Parse(number) - 1;
        resultJArray [captureIndex][numberMatchIndex] = numberAdjustedToZeroBase;
    }
}
MatchCollection matches=new Regex(@“^(?\[(?:[1-9]\d{0,7}(?:),(?=\d)){2,})+$”。matches(inputText);
如果(matches.Count!=1)返回;
CaptureCollection captures=匹配[0]。组[“集”]。捕获;
var resultJArray=newint[captures.Count][];
var numbersRegex=新的正则表达式(@“\d+”);
对于(int captureIndex=0;captureIndex
关于
\d+
和全局标志呢?

下面的正则表达式将验证并吐出括号内[]组的匹配组,以及其中的每个数字

(?:([1-9][0-9]*)\,?){2,}



[1][5]  -  fail
[1]  -  fail
[]  -  fail
[a,b,c][5]  -  fail
[1,2,3,4]  -  pass
[1,2,3,4,5,6,7,8][5,6,7,8]  -  pass
[1,2,3,4][5,6,7,8][534,63433,73434,8343434]  -  pass
首先,任何带有纯parenthasis的
(regex)
都是一个捕获组。这意味着正则表达式引擎将捕获(存储该组匹配的位置)。为了避免这种情况(当您不需要它时,请使用
(?:regex)
。我在上面做过

索引0是特殊的,它意味着整个父级。即匹配。组(0)。值总是与匹配。值和匹配。组(0)。捕获(0)。值。因此,可以考虑组和捕获集合从索引1开始。

正如您在下面看到的,每个匹配都包含一个括号内的数字组。您需要从每个匹配的组1中捕获1-n

foreach (Match match in matches)
{
   // [1,2]
   // use captures 1-n from the first group.
   for (int i = 1; i < match.Group[1].Captures.Count; i++)
   {
      int number = int.Parse(match.Group[1].Captures[i]);
      if (number == 0)
         throw new Exception ("Cannot be 0.");
   }
}

Match[0] => [1,2,3,4]
  Group[0] => [1,2,3,4]
    Capture[0] => [1,2,3,4]
  Group[1] => 4
    Capture[0] => 1
    Capture[1] => 2
    Capture[2] => 3
    Capture[3] => 4
Match[1] => [5,6,7,8]
  Group[0] => [5,6,7,8]
    Capture[0] => [5,6,7,8]
  Group[1] => 8
    Capture[0] => 5
    Capture[1] => 6
    Capture[2] => 7
    Capture[3] => 8
Match[2] => [534,63433,73434,8343434]
  Group[0] => [534,63433,73434,8343434]
    Capture[0] => [534,63433,73434,8343434]
  Group[1] => 8343434
    Capture[0] => 534
    Capture[1] => 63433
    Capture[2] => 73434
    Capture[3] => 8343434
foreach(匹配中的匹配)
{
// [1,2]
//使用从第一组捕获的1-n。
对于(int i=1;i[1,2,3,4]
组[0]=>[1,2,3,4]
捕获[0]=>[1,2,3,4]
组[1]=>4
捕获[0]=>1
捕获[1]=>2
捕获[2]=>3
捕获[3]=>4
匹配[1]=>[5,6,7,8]
组[0]=>[5,6,7,8]
捕获[0]=>[5,6,7,8]
组[1]=>8
捕获[0]=>5
捕获[1]=>6
捕获[2]=>7
捕获[3]=>8
匹配[2]=>[534634337343483434]
组[0]=>[534634337343483434]
捕获[0]=>[534634337343483434]
组[1]=>83434
捕获[0]=>534
捕获[1]=>63433
捕获[2]=>73434
捕获[3]=>83434
\G
使匹配从上次匹配的开始处开始(因此您不会匹配
[1,2][3,4]
)。
{2,}
满足您的要求,即每个匹配至少有2个数字


即使存在0,表达式也将匹配。我建议您将该验证与其他非正则表达式一起使用。这将使正则表达式更简单。

出于我不能随意透露的原因;)输入中不允许单独使用0,因此[1-9]+[\d]*。什么是全球旗帜?你能不能只用[1-9]+或者我误解了你的问题?@Dve,数字可以是10、100、1000。。。只是不是0。在这种情况下,[1-9][0-9]*就足够了。对于数字匹配部分来说,这是一个更简洁的表达式,唯一的问题是它匹配[0,1,2,3]中的1,2,3,但如果它包含0,我需要排除整个组,因此也会使整个输入字符串无效,即“[0,1,2,3][4,5,6,7]”即使第二组通过,也应失败。
string input = "[1,2,3,4][5,6,7,8][534,63433,73434,8343434]";
string pattern = @"\G(?:\[(?:(\d+)(?:,|(?=\]))){2,}\])";//\])+$";
MatchCollection matches = Regex.Matches (input, pattern);
foreach (Match match in matches)
{
   // [1,2]
   // use captures 1-n from the first group.
   for (int i = 1; i < match.Group[1].Captures.Count; i++)
   {
      int number = int.Parse(match.Group[1].Captures[i]);
      if (number == 0)
         throw new Exception ("Cannot be 0.");
   }
}

Match[0] => [1,2,3,4]
  Group[0] => [1,2,3,4]
    Capture[0] => [1,2,3,4]
  Group[1] => 4
    Capture[0] => 1
    Capture[1] => 2
    Capture[2] => 3
    Capture[3] => 4
Match[1] => [5,6,7,8]
  Group[0] => [5,6,7,8]
    Capture[0] => [5,6,7,8]
  Group[1] => 8
    Capture[0] => 5
    Capture[1] => 6
    Capture[2] => 7
    Capture[3] => 8
Match[2] => [534,63433,73434,8343434]
  Group[0] => [534,63433,73434,8343434]
    Capture[0] => [534,63433,73434,8343434]
  Group[1] => 8343434
    Capture[0] => 534
    Capture[1] => 63433
    Capture[2] => 73434
    Capture[3] => 8343434