Проверьте группы регулярных выражений с помощью OR, если обе группы присутствуют в коде Java - PullRequest
0 голосов
/ 15 февраля 2020

Необходимо проверить формат, в котором может присутствовать транспорт и протокол или оба. Я применил это регулярное выражение для проверки обеих групп. Но когда любая проверка успешна, она не проверяет другую группу, как в коде. Примечание: транспорт может принимать tcp, sctp или udp, а протокол может принимать радиус, диаметр и tacacs +.

Подобный пример, если транспорт и протокол являются частью URL, и если формат транспорта правильный и проверяется со значением, указанным в Regex, затем возвращает true, даже если значение протокола недопустимо.

Java Код:

String pattern = "((?=.*;transport=(tcp|sctp|udp)\\b)|(?=.*;protocol=(diameter|radius|tacacs+)\\b))";
String url = "transport=tcp;protocol=aradius";
    Pattern regExPattern = Pattern.compile(pattern);
    if(regExPattern.matcher(url).find()) {
        return true;
    } else {
        return false;
    }

Возвращает значение true, поскольку успешно проверяет транспорт но не в состоянии проверить значения протокола.

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Сложность заключается в том, что транспорт и протокол являются необязательными и отображаются в любом порядке. Чтобы сделать это в одном регулярном выражении, у меня есть чередование с использованием |, где в первом альтернативном варианте сначала сканируется транспортный параметр, а параметр протокола является необязательным, а во втором - все наоборот. Для реализации необязательного регулярного выражения A, которое может появляться далеко во входном потоке, мой подход заключается в использовании:

(.*(?<tag>A)|) Если во входном потоке появляется регулярное выражение A, найдите A, иначе сканировать без символов. Но в любом случае есть совпадение.

Вы не можете использовать:

.*(?<tag>A)?, потому что механизм регулярных выражений удовлетворяет это тривиально, сканируя 0 символов и никогда не сканируя A.

Регулярное выражение:

;transport=(?<transport1>tcp|sctp|udp)\b(.*;protocol=(?<protocol1>diameter|radius|tacacs+)\b|)|;protocol=(?<protocol2>diameter|radius|tacacs+)\b(.*;transport=(?<transport2>tcp|sctp|udp)\b|)

См. Демонстрационное выражение regex

Программа:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class Test
{
    public static void main(String[] args) {
        String tests[] = {
            "aaa;transport=tcp  ;protocol=radius",
            "aaa;protocol=diameter    ;transport=udp",
            "aaa;transport=sctp",
            "aaa;protocol=tacacs",
            "aaaa"
        };
        for (String test: tests) {
            Pattern pattern = Pattern.compile(";transport=(?<transport1>tcp|sctp|udp)\\b(.*;protocol=(?<protocol1>diameter|radius|tacacs+)\\b|)|;protocol=(?<protocol2>diameter|radius|tacacs+)\\b(.*;transport=(?<transport2>tcp|sctp|udp)\\b|)");
            System.out.println(test);
            Matcher m = pattern.matcher(test);
            if (m.find()) {
                String protocol = m.group("protocol1") == null ? m.group("protocol2") :  m.group("protocol1");
                String transport = m.group("transport1") == null ? m.group("transport2") : m.group("transport1");
                if (protocol != null) {
                    System.out.println("   protocol=" + protocol);
                }
                if (transport != null) {
                    System.out.println("   transport=" + transport);
                }
            }
        }
    }
}

Отпечатки:

aaa;transport=tcp  ;protocol=radius
   protocol=radius
   transport=tcp
aaa;protocol=diameter    ;transport=udp
   protocol=diameter
   transport=udp
aaa;transport=sctp
   transport=sctp
aaa;protocol=tacacs
   protocol=tacacs
aaaa

Примечание

Было бы проще использовать два отдельных регулярных выражения и два вызова find для сканирования значений транспорта и протокола. По крайней мере, регулярные выражения были бы намного проще.

0 голосов
/ 15 февраля 2020

Я не уверен на 100%, какие строки должны быть обнаружены как действительные, но позвольте мне привести пример:

import java.util.regex.Pattern;

public class Main
{

    private static void check(String s,Pattern regExPattern)
    {
        boolean matches=regExPattern.matcher(s).matches();
        System.out.println(s);
        System.out.println("matches:"+regExPattern.matcher(s).matches()+", find:"+regExPattern.matcher(s).find());
        System.out.println();
    }

    public static void main(String[] args) throws Exception
    {
        String pattern = "((.+=.+;transport=(tcp|sctp|udp))||(.+=.+;protocol=(diameter|radius|tacacs\\+)))";
        Pattern regExPattern = Pattern.compile(pattern);

        check("transport=tcp;protocol=diameter", regExPattern);
        check("transport=udp", regExPattern);
        check("protocol=radius", regExPattern);
        check("other=other;protocol=radius", regExPattern);
        check("other=other;transport=sctp", regExPattern);
        check("wrong;protocol=tacacs+", regExPattern);
        check("wrong;transport=tcp", regExPattern);
        check("wrong;wrong", regExPattern);
        check("something else;transport=tcp;protocol=diameter;something else", regExPattern);
    }
}

Выходы:

transport=tcp;protocol=diameter
matches:true, find:true

transport=udp
matches:false, find:true

protocol=radius
matches:false, find:true

other=other;protocol=radius
matches:true, find:true

other=other;transport=sctp
matches:true, find:true

wrong;protocol=tacacs+
matches:false, find:true

wrong;transport=tcps
matches:false, find:true

wrong;wrong
matches:false, find:true

something else;transport=tcp;protocol=diameter;something else
matches:false, find:true

Я заменил ? на .+, поскольку ? соответствует только одному символу, .+ соответствует более чем одному символу. Тогда вы можете использовать match() вместо find().

match () требует, чтобы вся строка соответствовала шаблону. find () требует, чтобы только часть строки соответствовала части шаблона. Я думаю, что вы хотели сопоставить (не найти).

Я заменил .* на .+, потому что .* соответствует любому количеству символов (включая ноль), но я предполагаю, что вы хотите соответствовать только по крайней мере один символ здесь.

Я удалил \\b, потому что это соответствует символу b буквально, что, кажется, не то, что вы хотите.

Я заменил tacacs+ на tacacs\\+, потому что Вы хотели соответствовать +, буквально не совпадая со всеми всеми словами, которые начинаются с tacacs и любым числом s, таким как tacacsssssss.

Веб-сайт https://regex101.com/ является очень полезно проверять регулярные выражения, потому что они помечают части шаблона цветами и объясняют, что означают эти части.

Вместо использования сложных выражений, которые вы не понимаете, вы можете проверить две части по отдельности, а затем написать if (matches || matches2)... оператор, который проверяет, совпадает ли хотя бы один из обоих:

import java.util.regex.Pattern;

public class Main
{

    private static void check(String s, String pattern1, String pattern2)
    {
        System.out.println(s);
        boolean matches1 = s.matches(pattern1);
        boolean matches2 = s.matches(pattern2);
        if (matches1 || matches2)
        {
            System.out.println("matches");
        }
        else
        {
            System.out.println("does not match");
        }
    }

    public static void main(String[] args) throws Exception
    {
        String pattern1 = ".*;transport=(tcp|sctp|udp).*";
        String pattern2 = ".*;protocol=(diameter|radius|tacacs\\+).*";

        check("transport=tcp;protocol=diameter", pattern1, pattern2);
        check("transport=udp", pattern1, pattern2);
        check("protocol=radius", pattern1, pattern2);
        check("other=other;protocol=radius", pattern1, pattern2);
        check("other=other;transport=sctp", pattern1, pattern2);
        check("wrong;protocol=tacacs+", pattern1, pattern2);
        check("wrong;transport=tcp", pattern1, pattern2);
        check("wrong;wrong", pattern1, pattern2);
        check("something else;transport=tcp;protocol=diameter;something else", pattern1, pattern2);
    }
}

Выходы:

transport=tcp;protocol=diameter
matches
transport=udp
does not match
protocol=radius
does not match
other=other;protocol=radius
matches
other=other;transport=sctp
matches
wrong;protocol=tacacs+
matches
wrong;transport=tcp
matches
wrong;wrong
does not match
something else;transport=tcp;protocol=diameter;something else
matches
...