Regex to catch these patterns recursively

有些话、适合烂在心里 提交于 2020-01-25 20:15:06

问题


    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}))?");

Currently my Regex will accept the following types of IP address input, but only one input type at a time:

  • ip: "47.1.2.3"
  • range: "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"

I would like to modify my regex to accept combinations of these separated by a comma or space. Ideally the regex would have named capture groups as listed above to make handling easier.

I want the following to also be a valid input, but I want to be able to pull out the matches described above with named groups.

"47.1.2.3 to 4, 47.1.2.7, 47.1.3.9-47.1.3.19"

I'm attempting to use the regex to verify input into a text field. The following code is the textfield:

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();
            }
        }
    });

}

//class methods.... }

This is the RegexFormatter Class:

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:


The ip parts are pretty unique, there should be no problem with
overlapping parts during a match using whitespace and/or comma as separator.

You probably need two versions of the same regex.
One to validate, one to extract.

The one to extract is just your original regex used in a global match.
This is used after a validation.

The validation one is below. It matches multiple ip parts at once using
the anchors ^$ with the original quantified regex embedded between using
the required separator [\s,]+.

Not sure if this will work for your validation code, but if entering a single ip part now, works, then this should.

Validation regex:

"^(?:\\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,]+))+$"

Formatted:

 ^     
 (?:
      \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,]+  
      )
 )+
 $  

edit: add group names to extraction regex.

 # "(?<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} 
      )
 )?


来源:https://stackoverflow.com/questions/33509420/regex-to-catch-these-patterns-recursively

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!