Regex для рекурсивного перехвата этих шаблонов

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

В настоящее время мое регулярное выражение будет принимать следующие типы ввода IP-адреса, но только один тип ввода за раз:

  • ip: "47.1.2.3"
  • диапазон: "47.1.2.3-4"
  • диапазон IP-адресов: «47.1.2.3-47.1.2.4»
  • IP в диапазоне: "47.1.2.3 до 4"
  • диапазон IP-адресов: «от 47.1.2.3 до 47.1.2.4»
  • IP-CIDR: "47.1.2.4/32"
  • Маска IP: "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
}

}


person Jamie Snipes    schedule 03.11.2015    source источник
comment
Но он также принимает список: regex101.com/r/jS2sD6/1   -  person Lol4t0    schedule 04.11.2015
comment
Добавлен дополнительный код для объяснения. Я использую его для проверки ввода. Как только запятая введена, мой ввод больше не действителен.   -  person Jamie Snipes    schedule 04.11.2015
comment
Вместо одного регулярного выражения супер-пупера совершенно смехотворно безумной сложности я бы порекомендовал разделить ваш ввод на запятые и проверить каждое отдельное поле отдельно. Регулярные выражения хороши и все такое, но они не являются абсолютным швейцарским армейским ножом программирования, как многие люди, кажется, думают, что они есть, и попытка заставить их играть эту роль часто приводит к нежелательным и неожиданным последствиям...   -  person twalberg    schedule 04.11.2015
comment
например: regex101.com/r/jS2sD6/2 ?   -  person Lol4t0    schedule 04.11.2015
comment
Также я считаю, что эту задачу не следует выполнять с помощью регулярного выражения: даже на этом этапе оно огромно и все еще не проходит базовый тест: regex101.com/r/jS2sD6/3   -  person Lol4t0    schedule 04.11.2015
comment
Вы должны использовать запятую в качестве разделителя списка, потому что, если вы используете пробел, регистр IP-маски нельзя отличить от списка двух простых IP-адресов. То, что вы пытаетесь сделать, является безумным использованием регулярных выражений - и, вероятно, оно никогда не сработает при загрузке. Я занимаюсь регулярными выражениями более 30 лет, пишу их каждый день, использовал их для анализа IP-адресов, и я никогда не пытался это сделать. То, что вы пытаетесь сделать, требует простого слоя токенизатора, который сначала разбивается, а затем регулярные выражения меньшего размера, чтобы соответствовать заданной последовательности токенов.   -  person Craig Estey    schedule 04.11.2015
comment
Итак, вы предлагаете использовать мой прослушиватель документов для разделения ввода на запятую, если она существует, и использовать регулярное выражение для проверки каждой подстроки? Моя цель состояла в том, чтобы использовать InputVerifyer для проверки пользовательского ввода в режиме реального времени. Поскольку для этого требуется только регулярное выражение, я предположил, что регулярное выражение может справиться с этим.   -  person Jamie Snipes    schedule 04.11.2015


Ответы (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} 
      )
 )?
person Community    schedule 04.11.2015
comment
Он проверяет, но есть ли способ получить именованные группы. т.е. определить, какое совпадение с именованной группой захвата? - person Jamie Snipes; 04.11.2015
comment
Я был уверен, что у тебя есть ответ, кстати. Вы должны быть официальным экспертом по регулярным выражениям для Stack - person Jamie Snipes; 04.11.2015
comment
@JamieSnipes - Хорошо, добавил имена групп в регулярное выражение. Вам нужно будет изучить регулярное выражение Java, чтобы получить доступ к именам захвата в сопоставителе. Я думаю, что это то же самое, что и нумерация по большей части. - person ; 04.11.2015