Validasi grup Regex dengan OR ketika kedua grup ada dalam kode Java

Perlu memvalidasi format di mana salah satu transport dan protokol bisa ada atau keduanya bisa ada. Saya telah menerapkan ekspresi reguler ini untuk memvalidasi kedua grup. Namun ketika salah satu validasi berhasil, grup tersebut tidak memvalidasi grup lain, seperti pada kode. Catatan: transport dapat menerima tcp, sctp atau udp dan protokol dapat menerima radius, diameter dan tacacs+.

Misalnya, jika transport dan protokol merupakan bagian dari URL, dan jika format transport benar dan divalidasi dengan nilai yang diberikan di Regex, maka ia akan mengembalikan nilai true meskipun nilai protokol tidak valid.

Kode 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;
    }

Ini mengembalikan nilai benar, karena memvalidasi transportasi berhasil tetapi tidak dapat memvalidasi nilai protokol.


person ekansh    schedule 15.02.2020    source sumber


Jawaban (2)


Saya tidak 100% yakin string apa yang terdeteksi valid, tetapi izinkan saya mencoba memberi contoh:

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

Keluaran:

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

Saya mengganti ? dengan .+ karena ? hanya cocok dengan satu karakter, .+ cocok dengan lebih dari satu karakter. Kemudian Anda dapat menggunakan match(), bukan find().

match() mengharuskan seluruh string cocok dengan polanya. find() mengharuskan hanya sebagian string yang cocok dengan sebagian pola. Saya pikir Anda ingin mencocokkan (bukan menemukan).

Saya mengganti .* dengan .+ karena .* cocok dengan sejumlah karakter (termasuk nol) tetapi saya berasumsi Anda hanya ingin mencocokkan setidaknya satu karakter di sini.

Saya menghapus \\b karena itu cocok dengan karakter b secara harfiah yang sepertinya bukan yang Anda inginkan.

Saya mengganti tacacs+ dengan tacacs\\+ karena Anda ingin mencocokkan + secara harfiah tidak cocok dengan semua kata yang dimulai dengan tacacs dan sejumlah s seperti tacacsssssss.

Situs web https://regex101.com/ sangat membantu untuk menguji ekspresi reguler karena menandai bagian dari pola dengan warna dan menjelaskan arti bagian-bagiannya.

Daripada menggunakan ekspresi kompleks yang tidak Anda pahami, Anda dapat memeriksa dua bagian satu per satu dan kemudian menulis pernyataan if (matches || matches2)... yang memeriksa apakah setidaknya salah satu dari keduanya cocok:

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

Keluaran:

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
person Stefan    schedule 15.02.2020

Kerumitannya adalah transport dan protokol bersifat opsional dan muncul dalam urutan apa pun. Untuk melakukan ini di satu regex saya memiliki pergantian menggunakan | di mana pada alternatif pertama parameter transport dipindai terlebih dahulu dan parameter protokol bersifat opsional dan pada alternatif kedua semuanya dibalik. Untuk mengimplementasikan ekspresi reguler opsional A yang dapat muncul jauh di aliran input, pendekatan saya adalah menggunakan:

(.*(?<tag>A)|) Jika ekspresi reguler A muncul di aliran input, pindai A, jika tidak, jangan pindai karakter apa pun. Tapi bagaimanapun juga, ada kecocokan.

Anda tidak dapat menggunakan:

.*(?<tag>A)? karena mesin regex memenuhi hal ini dengan memindai 0 karakter dan tidak pernah memindai A.

Regexnya:

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

Lihat demo regex

Program:

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

Cetakan:

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

Catatan

Akan lebih mudah untuk menggunakan dua ekspresi reguler terpisah dan dua panggilan ke find untuk memindai nilai transport dan protokol. Setidaknya ekspresi reguler akan jauh lebih sederhana.

person Booboo    schedule 15.02.2020