ตรวจสอบกลุ่ม Regex ด้วย OR เมื่อทั้งสองกลุ่มมีอยู่ในโค้ด Java

จำเป็นต้องตรวจสอบรูปแบบที่สามารถแสดงการขนส่งและโปรโตคอลอย่างใดอย่างหนึ่งหรือทั้งสองอย่างได้ ฉันใช้ regex นี้เพื่อตรวจสอบทั้งสองกลุ่ม แต่เมื่อการตรวจสอบความถูกต้องรายการใดรายการหนึ่งสำเร็จ จะไม่ตรวจสอบความถูกต้องของกลุ่มอื่น เช่นเดียวกับในโค้ด หมายเหตุ: การขนส่งยอมรับ tcp, sctp หรือ udp และโปรโตคอลยอมรับรัศมี เส้นผ่านศูนย์กลาง และ tacacs+ ได้

เช่น หากทั้งการขนส่งและโปรโตคอลเป็นส่วนหนึ่งของ URL และหากรูปแบบของการขนส่งถูกต้องและตรวจสอบด้วยค่าที่ระบุใน Regex ก็จะคืนค่าเป็นจริงแม้ว่าค่าของโปรโตคอลจะไม่ถูกต้องก็ตาม

รหัสจาวา:

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

ค่านี้คืนค่าจริง เนื่องจากตรวจสอบความถูกต้องของการขนส่งได้สำเร็จ แต่ไม่สามารถตรวจสอบค่าโปรโตคอลได้


person ekansh    schedule 15.02.2020    source แหล่งที่มา


คำตอบ (2)


ฉันไม่แน่ใจ 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
person Stefan    schedule 15.02.2020

ภาวะแทรกซ้อนคือการขนส่งและโปรโตคอลเป็นทั้งทางเลือกและปรากฏในลำดับใดก็ได้ หากต้องการทำสิ่งนี้ใน หนึ่ง regex ฉันมีตัวเลือกอื่นโดยใช้ | โดยที่ทางเลือกแรกพารามิเตอร์การขนส่งจะถูกสแกนก่อนและพารามิเตอร์โปรโตคอลเป็นทางเลือกและในทางเลือกที่สองจะกลับรายการ หากต้องการใช้นิพจน์ทั่วไปที่เป็นตัวเลือก A ที่สามารถปรากฏไกลในอินพุตสตรีม แนวทางของฉันคือการใช้:

(.*(?<tag>A)|) หากนิพจน์ทั่วไป A ปรากฏในสตรีมอินพุต ให้สแกนหา A มิฉะนั้นจะไม่สแกนอักขระเลย แต่ไม่ว่าจะด้วยวิธีใดก็มีการแข่งขัน

คุณไม่สามารถใช้:

.*(?<tag>A)? เนื่องจากกลไก regex ตอบสนองสิ่งนี้เพียงเล็กน้อยด้วยการสแกน 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 สองครั้งเพื่อสแกนค่าการขนส่งและโปรโตคอล อย่างน้อยนิพจน์ทั่วไปก็จะง่ายกว่ามาก

person Booboo    schedule 15.02.2020