วิธีใช้ regex ในเมธอด String.contains () ใน Java


112

ฉันต้องการตรวจสอบว่าสตริงมีคำว่า "ร้านค้า" "ร้านค้า" และ "สินค้า" อยู่ในลำดับนั้นหรือไม่ไม่ว่าจะเป็นอะไรก็ตาม

ฉันพยายามใช้someString.contains(stores%store%product);และยัง.contains("stores%store%product");

ฉันจำเป็นต้องประกาศ regex อย่างชัดเจนและส่งต่อไปยังเมธอดนั้นหรือฉันไม่สามารถส่ง regex ได้เลย?

คำตอบ:


125

String.contains

String.containsทำงานร่วมกับ String, period มันใช้ไม่ได้กับ regex จะตรวจสอบว่า String ที่ระบุปรากฏใน String ปัจจุบันหรือไม่

โปรดทราบString.containsว่าไม่ได้ตรวจสอบขอบเขตของคำ เพียงแค่ตรวจสอบสตริงย่อย

โซลูชัน Regex

Regex มีประสิทธิภาพมากกว่าString.containsเนื่องจากคุณสามารถบังคับใช้ขอบเขตของคำกับคำหลัก (และอื่น ๆ อีกมากมาย) ซึ่งหมายความว่าคุณสามารถค้นหาคำหลักที่เป็นคำพูดมากกว่าแค่สตริง

ใช้String.matchesกับ regex ต่อไปนี้:

"(?s).*\\bstores\\b.*\\bstore\\b.*\\bproduct\\b.*"

RAW regex (ลบการ Escape ที่ทำในตัวอักษรสตริง - นี่คือสิ่งที่คุณจะได้รับเมื่อคุณพิมพ์สตริงด้านบน):

(?s).*\bstores\b.*\bstore\b.*\bproduct\b.*

การตรวจสอบสำหรับขอบเขตของคำเพื่อที่คุณจะไม่ได้รับการแข่งขัน\b restores store productsโปรดทราบว่าstores 3store_productถูกปฏิเสธเช่นกันเนื่องจากตัวเลขและ_ถือเป็นส่วนหนึ่งของคำ แต่ฉันสงสัยว่ากรณีนี้จะปรากฏในข้อความที่เป็นธรรมชาติ

เนื่องจากมีการตรวจสอบขอบเขตของคำทั้งสองด้านนิพจน์ด้านบนจะค้นหาคำที่ตรงกัน ในคำอื่น ๆstores stores productจะไม่ตรงกับ regex ข้างต้นตั้งแต่ที่คุณกำลังค้นหาคำโดยไม่ต้องstores

.โดยปกติจะจับคู่อักขระใด ๆยกเว้น อักขระบรรทัดใหม่จำนวนหนึ่ง (?s)ในตอนต้นทำให้.ตรงกับตัวละครใด ๆ โดยไม่มีข้อยกเว้น (ขอบคุณ Tim Pietzcker ที่ชี้ให้เห็นสิ่งนี้)


7
คุณอาจต้องการเพิ่ม(?s)จุดเริ่มต้นของ regex ในกรณีที่สตริงมีการขึ้นบรรทัดใหม่
Tim Pietzcker

ฉันกำลังตรวจสอบใน URL เช่นนี้ >> stores.nextag.com/store/4908844/product/1070625777/…
vipin8169

คุณช่วยอธิบายแบ็กสแลชแรกที่นี่ได้\\b
ไหม

1
@ vipin8169: ใน String คุณต้องเพิ่มเป็นสองเท่า\เพื่อระบุซิงเกิ้ล\จึง\\bจะถูกตีความตาม\bที่เห็นใน RAW regex \bตรงกับขอบเขตคำตามที่อธิบายไว้ข้างต้น
nhahtdh

หากจำเป็นต้องตรงกับ ".mydomain" ในสตริง แล้วมันจะอัพเดต regex ได้อย่างไร กรณีการใช้งานของฉันคือ "www.abc.mydomain.in.io" ที่มี. mydomain หรือไม่
Manmohan Soni


21

คุณสามารถใช้matchesวิธีการของคลาส String

boolean result = someString.matches("stores.*store.*product.*");

14
คุณจำเป็นต้องเริ่มต้นด้วยหรือมันจะตรงกับสตริงเริ่มต้นด้วย.* stores
shmosel

พยายามจับคู่ภูมิภาคทั้งหมดกับรูปแบบ ดูเหมือนว่า @shmosel จะใช่ไม่ใช่เหรอ?
Pieter De Bie

1
มันตรงกันแต่ไม่ได้ตรวจสอบว่าสตริงมีรูปแบบที่ตำแหน่งใด ๆ นี่ไม่ใช่วิธีแก้ปัญหาที่ OP มองหาฉันขอแนะนำให้ปรับแต่ง regexp
Gee Bee

2

หากคุณต้องการตรวจสอบว่าสตริงมีสตริงย่อยหรือไม่ใช้ regex สิ่งที่ใกล้เคียงที่สุดที่คุณสามารถทำได้คือการใช้ find () -

    private static final validPattern =   "\\bstores\\b.*\\bstore\\b.*\\bproduct\\b"
    Pattern pattern = Pattern.compile(validPattern);
    Matcher matcher = pattern.matcher(inputString);
    System.out.print(matcher.find()); // should print true or false.

สังเกตความแตกต่างระหว่างการจับคู่ () และ find () การจับคู่ () คืนค่าจริงหากสตริงทั้งหมดตรงกับรูปแบบที่กำหนด find () พยายามค้นหาสตริงย่อยที่ตรงกับรูปแบบในสตริงอินพุตที่กำหนด นอกจากนี้เมื่อใช้ find () คุณไม่จำเป็นต้องเพิ่มการจับคู่พิเศษเช่น - (? s) * ที่จุดเริ่มต้นและ. * ที่ส่วนท้ายของรูปแบบ regex ของคุณ


2
public static void main(String[] args) {
    String test = "something hear - to - find some to or tows";
    System.out.println("1.result: " + contains("- to -( \\w+) som", test, null));
    System.out.println("2.result: " + contains("- to -( \\w+) som", test, 5));
}
static boolean contains(String pattern, String text, Integer fromIndex){
    if(fromIndex != null && fromIndex < text.length())
        return Pattern.compile(pattern).matcher(text).find();

    return Pattern.compile(pattern).matcher(text).find();
}

1. ผลลัพธ์: จริง

2. ผลลัพธ์: จริง


fromIndexถูกละเว้นใช่หรือไม่? contains("something", test, 5) => true
PKeidel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.