【问题标题】:Regex to match a number or nothing正则表达式匹配一个数字或什么都不匹配
【发布时间】:2014-11-18 06:04:33
【问题描述】:

我需要一个可以匹配这样的正则表达式:

1234 <CIRCLE> 12 12 12 </CIRCLE>

1234 <RECTANGLE> 12 12 12 12 </RECTANGLE>

我来写这个正则表达式:

(\\d+?) <([A-Z]+?)> (\\d+?) (\\d+?) (\\d+?) (\\d*)? (</[A-Z]+?>)

当我尝试匹配矩形时它可以正常工作,但它不适用于圆形

问题是我的第五组没有捕捉到,虽然它应该是??

【问题讨论】:

  • 你想要什么作为输出,只是数字还是数字和标签内容?

标签: java regex capturing-group


【解决方案1】:

试试

(\\d+?) <([A-Z]+?)> (\\d+?) (\\d+?) (\\d+?) (\\d+ )?(</[A-Z]+?>)

(我更改了最后一个“\d”组以使空格也是可选的。)

【讨论】:

    【解决方案2】:

    那是因为只有 (\\d*)? 部分是可选的,但它之前和之后的空格是强制性的,所以你最终需要两个空格,如果最后一个 (\\d*) 找不到。尝试使用类似的东西

    (\\d+?) <([A-Z]+?)> (:?(\\d+?) ){3,4}(</[A-Z]+?>)
    

    哦,如果你想确保结束标签与开始标签相同,你可以使用像 \\1 这样的组引用来表示来自第一组的匹配。因此,也许将您的正则表达式更新为类似

    (\\d+?) <([A-Z]+?)> (:?(\\d+?) ){3,4}(</\\2>)
    //        ^^^^^^^-----------------------^^^ 
    //        group 2                       here value need to match one from group 2
    

    【讨论】:

    • @FrancisGroleau 我不确定你的意思。组 0 表示整个匹配,而存储在组中的其余部分匹配从 1 开始索引,因此 (\\d+?) 是组 1,([A-Z]+?)> 内的部分是组 2,依此类推。
    【解决方案3】:

    仅针对数字的解决方案:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import javax.annotation.Nonnull;
    
    public class Q26005150
    {
        private static final Pattern P = Pattern.compile("(\\d+)");
    
        public static void main(String[] args)
        {
            final String s1 = "1234 <CIRCLE> 12 12 12 </CIRCLE>";
            final String s2 = "1234 <RECTANGLE> 12 12 12 12 </RECTANGLE>";
    
            final List<Integer> l1 = getAllMatches(s1);
            final List<Integer> l2 = getAllMatches(s2);
    
            System.out.println("l1 = " + l1);
            System.out.println("l2 = " + l2);
        }
    
        private static List<Integer> getAllMatches(@Nonnull final String s)
        {
            final Matcher m = P.matcher(s);
            final List<Integer> matches = new ArrayList<Integer>();
            while(m.find())
            {
                matches.add(Integer.valueOf(m.group(1)));
            }
            return matches;
        }
    }
    

    输出:

    l1 = [1234, 12, 12, 12]
    l2 = [1234, 12, 12, 12, 12]
    

    Answer on GitHub

    Stackoverflow GitHub repository

    【讨论】:

      【解决方案4】:

      数字和标签的解决方案

      private static final Pattern P = Pattern.compile("(<\/?(\w+)>|(\d+))");
      
      public static void main(String[] args)
      {
          final String s1 = "1234 <CIRCLE> 12 12 12 </CIRCLE>";
          final String s2 = "1234 <RECTANGLE> 12 12 12 12 </RECTANGLE>";
      
          final List<String> l1 = getAllMatches(s1);
          final List<String> l2 = getAllMatches(s2);
      
          System.out.println("l1 = " + l1);
          System.out.println("l2 = " + l2);
      }
      
      private static List<String> getAllMatches(@Nonnull final String s)
      {
          final Matcher m = P.matcher(s);
          final List<String> matches = new ArrayList<String>();
          while(m.find())
          {
              final String match = m.group(1);
              matches.add(match);
          }
          return matches;
      }
      

      输出:

      l1 = [1234, <CIRCLE>, 12, 12, 12, </CIRCLE>]
      l2 = [1234, <RECTANGLE>, 12, 12, 12, 12, </RECTANGLE>]
      

      Answer on GitHub

      Stackoverflow GitHub repository

      【讨论】:

        【解决方案5】:

        假设“”之间的标签必须匹配并且它们之间的数字相同
        使用这种模式

        ^\d+\s<([A-Z]+)>\s(\d+\s)(\2)+<\/(\1)>$  
        

        Demo

        或者如果中间的数字不必相同或可选:

        ^\d+\s<([A-Z]+)>\s(\d+\s)*<\/(\1)>$
        

        【讨论】:

          猜你喜欢
          • 2021-08-08
          • 2014-02-07
          • 1970-01-01
          • 2016-10-21
          • 2014-01-07
          • 2021-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多