正则表达式以递归方式捕获这些模式

时间:2015-11-03 21:29:46

标签: regex regex-greedy

    java.util.regex.Pattern ips
        = java.util.regex.Pattern.compile("(\\d{1,3}(?:\\.\\d{1,3}){2}\\.(\\d{1,3}))(?:(?:-|\\s+to\\s+)(\\d{1,3}(?![\\d\\.]))|(?:-|\\s*to\\s+)(\\d{1,3}(?:\\.\\d{1,3}){3})|\\s+(25\\d(?:\\.\\d{1,3}){3})|\\s*\\/(\\d{1,3}))?");

目前我的Regex将接受以下类型的IP地址输入,但一次只能接受一种输入类型:

  • ip:" 47.1.2.3"
  • 范围:" 47.1.2.3-4"
  • ip range:" 47.1.2.3-47.1.2.4"
  • ip to range:" 47.1.2.3 to 4"
  • ip to ip range:" 47.1.2.3 to 47.1.2.4"
  • ip CIDR:" 47.1.2.4/32"
  • ip Mask:" 47.1.2.4 255.255.255.255"

我想修改我的正则表达式以接受用逗号或空格分隔的这些组合。理想情况下,正则表达式将命名为上面列出的捕获组,以便于处理。

我希望以下内容也是一个有效的输入,但我希望能够使用命名组提取上述匹配。

"47.1.2.3 to 4, 47.1.2.7, 47.1.3.9-47.1.3.19"

我试图使用正则表达式来验证文本字段中的输入。以下代码是文本字段:

public class HostCollectionTextField extends JFormattedTextField implements CellEditor, MouseListener {

ArrayList listeners = new ArrayList();
HostCollection hc;
java.util.regex.Pattern ips
        = java.util.regex.Pattern.compile("(\\d{1,3}(?:\\.\\d{1,3}){2}\\.(\\d{1,3}))(?:(?:-|\\s+to\\s+)(\\d{1,3}(?![\\d\\.]))|(?:-|\\s*to\\s+)(\\d{1,3}(?:\\.\\d{1,3}){3})|\\s+(25\\d(?:\\.\\d{1,3}){3})|\\s*\\/(\\d{1,3}))?");

public HostCollectionTextField() {
    this.addMouseListener(this);
    this.hc = new HostCollection();

    this.setFormatterFactory(new AbstractFormatterFactory() {

        @Override
        public JFormattedTextField.AbstractFormatter getFormatter(JFormattedTextField tf) {
            RegexFormatter f = new RegexFormatter(ips);
            return f;
        }
    });
    this.getDocument().addDocumentListener(new DocListener(this));
    addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            if (stopCellEditing()) {
                fireEditingStopped();
            }
        }
    });

}

//类方法.... }

这是RegexFormatter类:

public class RegexFormatter extends DefaultFormatter {

protected java.util.regex.Matcher matcher;

public RegexFormatter(java.util.regex.Pattern regex) {
    setOverwriteMode(false);
    matcher = regex.matcher(""); // create a Matcher for the regular expression
}

public Object stringToValue(String string) throws java.text.ParseException {
    if (string == null) {
        return null;
    }
    matcher.reset(string); // set 'string' as the matcher's input

    if (!matcher.matches()) // Does 'string' match the regular expression?
    {
        throw new java.text.ParseException("does not match regex", 0);
    }

    // If we get this far, then it did match.
    return super.stringToValue(string); // will honor the 'valueClass' property
}

}

1 个答案:

答案 0 :(得分:1)

ip部分非常独特,应该没有问题 使用空格和/或逗号作为分隔符在匹配期间重叠部分。

你可能需要同一个正则表达式的两个版本 一个要验证,一个要提取。

要提取的是您在全局匹配中使用的原始正则表达式 这在验证后使用。

验证一个在下面。它使用
一次匹配多个ip部分 锚点^$与原始量化的正则表达式之间嵌入使用
所需的分隔符[\s,]+

不确定这是否适用于您的验证码,但是如果输入 一个单独的ip部件现在,工作,然后这应该。

验证正则表达式:

"^(?:\\d{1,3}(?:\\.\\d{1,3}){2}\\.\\d{1,3}(?:(?:-|\\s+to\\s+)\\d{1,3}(?![\\d\\.])|(?:-|\\s*to\\s+)\\d{1,3}(?:\\.\\d{1,3}){3}|\\s+25\\d(?:\\.\\d{1,3}){3}|\\s*\\/\\d{1,3})?(?:[\\s,]*$|[\\s,]+))+$"

格式化:

 ^     
 (?:
      \d{1,3} 
      (?: \. \d{1,3} ){2}
      \.
      \d{1,3} 
      (?:
           (?: - | \s+ to \s+ )
           \d{1,3} 
           (?! [\d\.] )
        |  
           (?: - | \s* to \s+ )
           \d{1,3} 
           (?: \. \d{1,3} ){3}
        |  
           \s+ 
           25 \d 
           (?: \. \d{1,3} ){3}
        |  
           \s* \/
           \d{1,3} 
      )?

      (?:
           [\s,]* $ 
        |  
           [\s,]+  
      )
 )+
 $  

编辑:将组名添加到提取正则表达式。

 # "(?<IP>\\d{1,3}(?:\\.\\d{1,3}){2}\\.(?<From_Seg>\\d{1,3}))(?:(?:-|\\s+to\\s+)(?<To_Seg>\\d{1,3}(?![\\d\\.]))|(?:-|\\s*to\\s+)(?<To_Range>\\d{1,3}(?:\\.\\d{1,3}){3})|\\s+(?<Mask>25\\d(?:\\.\\d{1,3}){3})|\\s*/(?<Port>\\d{1,3}))?"

 (?<IP>                        # (1), IP
      \d{1,3} 
      (?: \. \d{1,3} ){2}
      \.
      (?<From_Seg> \d{1,3} )        # (2), From segment
 )
 (?:
      (?: - | \s+ to \s+ )
      (?<To_Seg>                    # (3), Dash/To segment
           \d{1,3} 
           (?! [\d\.] )
      )
   |  
      (?: - | \s* to \s+ )
      (?<To_Range>                  # (4), Dash/To range
           \d{1,3} 
           (?: \. \d{1,3} ){3}
      )
   |  
      \s+     
      (?<Mask>                      # (5), Mask
           25 \d 
           (?: \. \d{1,3} ){3}
      )
   |  
      \s* /     
      (?<Port>                      # (6), Port
           \d{1,3} 
      )
 )?