C# 正则表达式:从字符串中提取以逗号分隔的数字

C# 正则表达式:从字符串中提取以逗号分隔的数字,c#,.net,regex,powershell,C#,.net,Regex,Powershell,我需要使用任意数量的数字和空格从如下字符串中提取逗号分隔的数字: Expression type: Answer: (1, 2,3) 1,2,3 (1,3,4,5,77) 1,3,4,5,77 ( b(2,46,8,4,5, 52) y) 2,46,8,4,5,52 (a (3, 8,2, 1, 2, 9) x) 3,8,2,1,2,9 尝试以下模式: \((?:\s*\d+\s*,?)

我需要使用任意数量的数字和空格从如下字符串中提取逗号分隔的数字:

Expression type:            Answer:
(1, 2,3)                    1,2,3
(1,3,4,5,77)                1,3,4,5,77
( b(2,46,8,4,5, 52)    y)   2,46,8,4,5,52
(a (3, 8,2, 1, 2, 9) x)     3,8,2,1,2,9
尝试以下模式:

\((?:\s*\d+\s*,?)+\)
例如:

var results = Regex.Matches(input, @"\((?:\s*\d+\s*,?)+\)");
Console.WriteLine(results[0].Value); // (1,2,3)
如果您想将其转换为整数列表,可以使用Linq轻松完成:

var results = Regex.Matches(input, @"\((?:\s*(\d+)\s*,?)+\)")
                   .Cast<Match>()
                   .SelectMany(m => m.Groups.Cast<Group>()).Skip(1)
                   .SelectMany(g => g.Captures.Cast<Capture>())
                   .Select(c => Convert.ToInt32(c.Value));
或在查询语法中:

var results = 
    from m in Regex.Matches(input, @"\((?:\s*(\d+)\s*,?)+\)").Cast<Match>()
    from g in m.Groups.Cast<Group>().Skip(1)
    from c in g.Captures.Cast<Capture>()
    select Convert.ToInt32(c.Value);
尝试以下模式:

\((?:\s*\d+\s*,?)+\)
例如:

var results = Regex.Matches(input, @"\((?:\s*\d+\s*,?)+\)");
Console.WriteLine(results[0].Value); // (1,2,3)
如果您想将其转换为整数列表,可以使用Linq轻松完成:

var results = Regex.Matches(input, @"\((?:\s*(\d+)\s*,?)+\)")
                   .Cast<Match>()
                   .SelectMany(m => m.Groups.Cast<Group>()).Skip(1)
                   .SelectMany(g => g.Captures.Cast<Capture>())
                   .Select(c => Convert.ToInt32(c.Value));
或在查询语法中:

var results = 
    from m in Regex.Matches(input, @"\((?:\s*(\d+)\s*,?)+\)").Cast<Match>()
    from g in m.Groups.Cast<Group>().Skip(1)
    from c in g.Captures.Cast<Capture>()
    select Convert.ToInt32(c.Value);

你将一直拥有的搜索字符串是否像你发布的一样

数字1,数字2,数字3文本

编辑:您提供了新的示例,这些示例应该可以处理:

    string input = "( b(2,46,8,4,5, 52)    y)";
    input = input.Remove(" ","");
    var result = Regex.Matches(input, @"\(([0-9]+,)+[0-9]+\)");
    Console.WriteLine(result[0]);

你将一直拥有的搜索字符串是否像你发布的一样

数字1,数字2,数字3文本

编辑:您提供了新的示例,这些示例应该可以处理:

    string input = "( b(2,46,8,4,5, 52)    y)";
    input = input.Remove(" ","");
    var result = Regex.Matches(input, @"\(([0-9]+,)+[0-9]+\)");
    Console.WriteLine(result[0]);

鉴于也可能存在空间,这里有一个建议,对于更大的输入来说,更有效一些:

@"[(]\d+(?:,\d+)*[)]"
当然,您也可以用反斜杠转义括号。我只是想展示另一种选择,我个人觉得它更具可读性

如果您最终想要获得数字,而不是拆分正则表达式的结果,您可以立即捕获它们:

@"[(](?<numbers>\d+)(?:,(?<numbers>\d+))*[)]"

鉴于也可能存在空间,这里有一个建议,对于更大的输入来说,更有效一些:

@"[(]\d+(?:,\d+)*[)]"
当然,您也可以用反斜杠转义括号。我只是想展示另一种选择,我个人觉得它更具可读性

如果您最终想要获得数字,而不是拆分正则表达式的结果,您可以立即捕获它们:

@"[(](?<numbers>\d+)(?:,(?<numbers>\d+))*[)]"

我可能会使用这样的正则表达式:

\((\d+(?:\s*,\s*\d+)*)\)
$str = @(
    "(1, 2,3)"
  , "(1,3,4,5,77)"
  , "( b(2,46,8,4,5, 52)"
  , "(a (3, 8,2, 1, 2, 9) x)"
  , "(1)"
  , "(1 2, 3)"    # no match (no comma between 1st and 2nd number)
  , "( 1,2,3)"    # no match (leading whitespace before 1st number)
  , "(1,2,3 )"    # no match (trailing whitespace after last number)
  , "(1,2,)"      # no match (trailing comma)
)
$re  = '\((\d+(?:\s*,\s*\d+)*)\)'

$str | ? { $_ -match $re } | % { $matches[1] -replace '\s+', "" }
PowerShell代码如下:

\((\d+(?:\s*,\s*\d+)*)\)
$str = @(
    "(1, 2,3)"
  , "(1,3,4,5,77)"
  , "( b(2,46,8,4,5, 52)"
  , "(a (3, 8,2, 1, 2, 9) x)"
  , "(1)"
  , "(1 2, 3)"    # no match (no comma between 1st and 2nd number)
  , "( 1,2,3)"    # no match (leading whitespace before 1st number)
  , "(1,2,3 )"    # no match (trailing whitespace after last number)
  , "(1,2,)"      # no match (trailing comma)
)
$re  = '\((\d+(?:\s*,\s*\d+)*)\)'

$str | ? { $_ -match $re } | % { $matches[1] -replace '\s+', "" }
正则表达式将匹配一个子字符串,该子字符串以一个开括号开始,后跟一个逗号分隔的数字序列,该数字序列可能在逗号之前或之后包含任意数量的空格,并以一个右括号结束。空格随后由-replace指令删除

如果不希望匹配单个数字1,请将正则表达式更改为:

\((\d+(?:\s*,\s*\d+)+)\)
\(\s*(\d+(?:\s*,\s*\d+)*)\s*\)
如果希望在开始括号之后或结束括号之前允许空白,请将正则表达式更改为:

\((\d+(?:\s*,\s*\d+)+)\)
\(\s*(\d+(?:\s*,\s*\d+)*)\s*\)

我可能会使用这样的正则表达式:

\((\d+(?:\s*,\s*\d+)*)\)
$str = @(
    "(1, 2,3)"
  , "(1,3,4,5,77)"
  , "( b(2,46,8,4,5, 52)"
  , "(a (3, 8,2, 1, 2, 9) x)"
  , "(1)"
  , "(1 2, 3)"    # no match (no comma between 1st and 2nd number)
  , "( 1,2,3)"    # no match (leading whitespace before 1st number)
  , "(1,2,3 )"    # no match (trailing whitespace after last number)
  , "(1,2,)"      # no match (trailing comma)
)
$re  = '\((\d+(?:\s*,\s*\d+)*)\)'

$str | ? { $_ -match $re } | % { $matches[1] -replace '\s+', "" }
PowerShell代码如下:

\((\d+(?:\s*,\s*\d+)*)\)
$str = @(
    "(1, 2,3)"
  , "(1,3,4,5,77)"
  , "( b(2,46,8,4,5, 52)"
  , "(a (3, 8,2, 1, 2, 9) x)"
  , "(1)"
  , "(1 2, 3)"    # no match (no comma between 1st and 2nd number)
  , "( 1,2,3)"    # no match (leading whitespace before 1st number)
  , "(1,2,3 )"    # no match (trailing whitespace after last number)
  , "(1,2,)"      # no match (trailing comma)
)
$re  = '\((\d+(?:\s*,\s*\d+)*)\)'

$str | ? { $_ -match $re } | % { $matches[1] -replace '\s+', "" }
正则表达式将匹配一个子字符串,该子字符串以一个开括号开始,后跟一个逗号分隔的数字序列,该数字序列可能在逗号之前或之后包含任意数量的空格,并以一个右括号结束。空格随后由-replace指令删除

如果不希望匹配单个数字1,请将正则表达式更改为:

\((\d+(?:\s*,\s*\d+)+)\)
\(\s*(\d+(?:\s*,\s*\d+)*)\s*\)
如果希望在开始括号之后或结束括号之前允许空白,请将正则表达式更改为:

\((\d+(?:\s*,\s*\d+)+)\)
\(\s*(\d+(?:\s*,\s*\d+)*)\s*\)


a这其中哪些部分是可变的?b你试过什么?变量应该是这样的数字:数字,数字,…,括号中的数字可以是空格。我使用的是简单的分割技术,但这不是优雅的和错误的pronea这其中哪些部分是可变的?b你试过什么?变量应该是这样的数字:数字,数字,…,括号中的数字可以是空格。我使用的是简单的拆分技术,但这并不优雅,错误概率将捕获带有尾随逗号的单个数字,而不是整个1,2,3.@m.buettner当然会。结果[0]。正确的值将为1,2,3Oh。显然,现在还太早。。。您可以使该组不捕获?:\d+。。。我认为,这也是一个很好的实践。正则表达式将匹配由空格12分隔的数字以及带有尾随逗号1,2的数字序列,但不匹配前导逗号1,2。这将捕获带有尾随逗号的单个数字,而不是整个1,2,3。@m.buettner当然会。结果[0]。正确的值将为1,2,3Oh。显然,现在还太早。。。您可以使该组不捕获?:\d+。。。我认为,这也是一个很好的实践。正则表达式将匹配由空格12分隔的数字以及带有尾随逗号1,2的数字序列,但不匹配前导逗号1,2。这是正确的,但他的问题没有显示其他情况。我不确定他需要什么这个代码也会匹配以空格分隔的数字,例如12,3,但不会匹配单个数字,例如1。这是真的,但他的问题没有显示其他情况。我不确定他需要什么这个代码也会匹配由空格分隔的数字,例如12,3,但不会匹配单个数字,例如1。虽然我同意它更可读,但这不考虑空格。我也不知道你可以像那样重用组名。@p.s.w.g因为他不想在结果中包含空格,所以我会在使用正则表达式之前删除它们。@WhileTrueSleep+1,因为这完全符合要求
奥普的问题。但是在比赛结束后把它们去掉会更有效吗,因为字符串的大小会更小?@p.s.w.g我认为在你用正则表达式搜索之前去掉它们会更快。但这是一个我没有测量的猜测it@p.s.w.g不知怎的,在我的第一句话和句型之间,我又完全忘记了空格。。。我来编辑一下。关于组名,这只在.NET中可能,我认为这是引擎最有用的功能之一。虽然我同意它更可读,但这不考虑空格。我也不知道你可以像那样重用组名。@p.s.w.g因为他不想在结果中包含空格,所以我会在使用正则表达式之前删除它们。@WhileTrueSleep+1,因为这完全解决了OP的问题。但是在比赛结束后把它们去掉会更有效吗,因为字符串的大小会更小?@p.s.w.g我认为在你用正则表达式搜索之前去掉它们会更快。但这是一个我没有测量的猜测it@p.s.w.g不知怎的,在我的第一句话和句型之间,我又完全忘记了空格。。。我来编辑一下。关于组名,这只有在.NET中才可能实现,我认为这是引擎最有用的特性之一。