【问题标题】:Regex retrieve second capture group正则表达式检索第二个捕获组
【发布时间】:2015-02-14 09:43:50
【问题描述】:

我有以下字符串(CrLf 可能插入到{} 和() 之外)

{item1}, {item2} (2), {item3}    (4),  {item4}
(1), {item5},{item6}(5)

我正在尝试将每个项目与其组件分开,并使用正则表达式从中创建一个 JSON。

输出应该是这样的

{"name":"item1", "count":""}, {"name":"item2", "count":""}, {"name":"item3", "count":""}, {"name":"item4", "count":""}, {"name":"item5", "count":""},{"name":"item6", "count":""}

到目前为止,我已经关注regex,但它没有捕获第二组。

\{(.[^,\n\]]*)\}\s*[\((.\d)\)]*

我正在用

替换匹配项
{\"name\":\"${1}\", \"count\":\"${2}\"}

这是我的test link

我做错了什么?

第二个问题

是否可以将不计数的项目更改为零,以便我的第二个捕获组读取为 0?

例如,与其将{item1} 更改为{"name":"item1", "count":""},不如将​​其更改为{"name":"item1", "count":"0"}

【问题讨论】:

    标签: c# regex json


    【解决方案1】:

    您的第二个捕获组对于捕获数字信息(即[\((.\d)\)])无效,这就是没有捕获到任何信息的原因。此外,在捕获数字时使用 [0-9],它是 recommended,因为 \d 也可以捕获不需要的 unicode 定义的字符。

    以下正则表达式将仅捕获 2 个组(与 @revo 的答案不同,后者捕获了中间不必要的组)

    \{(.[^,\n\]]*)\}(?:\s*\(([0-9]+)\))?
    

    至于第二个要求,正则表达式用于从现有数据中捕获信息,据我所知,不可能注入不存在的信息。最简单的方法是在正则表达式运行后修复 JSON。

    或者,您可以在替换开始时包含0,这样任何空捕获将始终具有0 的值,并且任何捕获的仍然有效,但只需包含0开始,例如04/035等

    {\"name\":\"$1\", \"count\":\"0$2\"}
    

    【讨论】:

    • 零的好解决方案。我不知道 unicode 的情况,但是我的数据是 ascii 数据,所以我不会担心。但是我会使用@revo 的解决方案,因为他是第一个,希望你不介意:-)
    • @BobSort 我一点也不介意,但是,请记住他的回答确实捕获了一个额外的不必要的组,这意味着在您的替换中您需要引用$1 和$3, mines 使用非捕获组仅提取名称 + 值,这意味着您的替换保持原样。
    【解决方案2】:

    1- 您正在使用格式错误的正则表达式版本。 (使用字符序列内捕获的组[])

    2- 您没有在替换模式中包含第二个捕获的组。

    我将您的正则表达式更新为:

    \{(.[^,\n\]]*)\}\s*(\((\d*)\))?
    

    Live demo

    我将为这个问题提供一个更好的正则表达式。

    更新:

    {(\w+)}\s*(\((\d+)[),])?
    

    Live demo

    【讨论】:

    • 哦!我忘记更新 regex101(我在这里有${2} 的问题)。如果第二个捕获组不可用,我认为不可能用 0 替换 ${2}?
    • 是的@BobSort,您必须以编程方式将那些空的count 键替换为0。我也提供了我的正则表达式版本。
    【解决方案3】:

    没有 regex 的解决方案。我尝试使用substring 方法从字符串中提取数据,它似乎工作正常

    int start, end;
    
    String a = "{item1}, {item2} (2), {item3}    (4),  {item4}(1), {item5},{item6}(5)";
    
    string[] b = a.Split(',');
    
    foreach (String item in b)
    {
         Console.WriteLine(item);
    
         start=item.IndexOf('{') +1 ;
         end = item.IndexOf('}');
    
         Console.WriteLine(" \t Name : " + item.Substring(start,end-start));
    
          if (item.IndexOf('(')!=-1 )
          {    
               start = item.IndexOf('(');
    
               Console.WriteLine(" \t Count : " + item[start+1] );
           }
    
     }
    

    【讨论】:

    • 是的,您的解决方案有效。但是与您的工作相同的代码是Regex.Replace(ItemTooltip, @"\[\[\:(.[^,\n\]]*)\]\]\s*(\((\d)\))?", "{\"name\":\"${1}\", \"count\":\"${3}\"}"),这只是一行,如果您知道如何使用正则表达式,则无需担心单词索引。顺便说一句,如果项目名称中有逗号,则您的方法将中断,这就是为什么它们用大括号括起来。
    猜你喜欢
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 2013-05-07
    • 1970-01-01
    相关资源
    最近更新 更多