Regex ไม่ทำงานใน String.matches ()


147

ฉันมีโค้ดเล็ก ๆ นี้

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("[a-z]"))
    {
        System.out.println(s);
    }
}

ควรพิมพ์

dkoe

แต่มันไม่มีอะไรพิมพ์ !!


41
Java's matchesวาง ^ ไว้ที่จุดเริ่มต้นและ $ ที่ท้าย regexes สำหรับคุณ ดังนั้นmatches("[a-z]")จริง ๆ แล้วจะค้นหา / ^ [az] $ / แทน
Robino

ใช่ @Robino คุณพูดถูก
Mihir

1
แน่นอนถ้าคุณคาดหวังที่matchesจะมองหาสิ่งที่เกิดขึ้น[a-z]แล้วมันควรจะตรงกับพวกเขาทั้งหมดหรือไม่ ฉันจะไม่คาดหวังว่าmatchesจะตรวจสอบตัวละครแต่ละตัวทุกตัวกับ regex
PhilHibbs

@Robino: ฟังก์ชั่นนั้นอธิบาย / จัดทำไว้ที่ไหน?
Toru

@Toru บนหน้าเอกสาร java สำหรับ String.Matches - ที่ไหนอีก? Google ธรรมดา ๆ ของ "java string match document" เผยให้เห็นว่าในผลลัพธ์สูงสุดวลี "str.matches (regex) ให้ผลลัพธ์เหมือนกับการแสดงออก" คำสำคัญคือ "ตรง"
Robino

คำตอบ:


323

ยินดีต้อนรับสู่.matches()วิธีการที่ผิดของ Java ... มันพยายามและจับคู่อินพุตทั้งหมด น่าเสียดายที่ภาษาอื่น ๆ ได้ตามหลังชุดสูท :(

หากคุณต้องการดูว่า regex ตรงกับข้อความที่ป้อนให้ใช้Patterna Matcherและ.find()วิธีของ matcher หรือไม่:

Pattern p = Pattern.compile("[a-z]");
Matcher m = p.matcher(inputstring);
if (m.find())
    // match

หากสิ่งที่คุณต้องการแน่นอนเพื่อดูว่ามีการป้อนข้อมูลมีเพียงตัวอักษรตัวพิมพ์เล็กคุณสามารถใช้.matches()แต่คุณจำเป็นต้องตรงกับหนึ่งหรือมากกว่าหนึ่งตัวอักษร: ผนวกการเรียนตัวละครของคุณในขณะที่+ [a-z]+หรือการใช้งานและ^[a-z]+$.find()


2
ฉันพบบทเรียน 100s ออนไลน์ที่ไม่สมบูรณ์ ไม่พบสิ่งที่ดี คุณมีข้อเสนอแนะใด?
John

Thanx @fge .matches()สำหรับอธิบาย คุณอาจจะรู้ว่าทำไม.find()ทำงานช้าดังนั้นในตัวอย่างนี้ ?
Konstantin Konopko

3
ภาษาอื่นตามหลังชุดว่าหมายถึงอะไร จากสิ่งที่ฉันรู้เพียงภาษา C ++ มีชุดเทียบเท่าวิธีการ - และregex_search regex_matchใน Python re.matchเพียงจับคู่การแข่งขันที่จุดเริ่มต้นของสตริง (ราวกับว่ามันเป็น\Apattern) และ Python 3.x มี.fullmatch()วิธีการที่ดี ใน JS, Go, PHP และ. NET, ไม่มีวิธีการ regex ที่ยึดการแข่งขันโดยปริยาย ElasticSearch, XML Schema และ HTML5 / Validators รูปแบบ Angluar จะยึดตามค่าเริ่มต้นเสมอ ใน Swift / Objective C มีวิธีการยึดรูปแบบเมื่อเริ่มต้นด้วยตัวเลือก
Wiktor Stribiżew

มีวิธีการในการทำเช่นนี้?
พระคาร์ดินัล - Reinstate Monica

44

[a-z]ตรงกับอักขระเดี่ยวระหว่าง a และ z "d"ตัวอย่างเช่นถ้าสตริงของคุณเป็นเพียงแค่มันจะจับคู่และพิมพ์ออกมา

คุณต้องเปลี่ยน regex ของคุณเพื่อ[a-z]+ให้ตรงกับหนึ่งตัวอักษรหรือมากกว่า


12
แน่นอนว่ามันตรงกับถ่านตัวเดียวนั่นคือสิ่งที่ regexp ทำ! อย่างไรก็ตามสิ่งที่ไม่ชัดเจน (และไม่ควรเป็นเช่นนั้น!) คือ java ทำให้คำนำหน้า^และคำต่อท้าย$อยู่รอบ ๆ regexp ที่จัดเตรียมไว้ให้แก้ไขโดยไม่ต้องการและสร้างข้อผิดพลาดแปลก ๆ พวกเขาไม่ควรทำเช่นนั้นเพราะนั่นไม่ใช่วิธีเริ่มต้น regexp ที่มีความหมาย
klaar

28

String.matchesส่งคืนว่าสตริงทั้งหมดตรงกับ regex ไม่ใช่แค่สตริงย่อยใด ๆ


3
สิ่งที่เป็นความจริงที่น่าเศร้าจริง ๆ คือคุณพูดถูก ฉันไม่รู้จริงๆว่าทำไมพวกเขาถึงทำแบบนี้
Hola Soy Edu Feliz Navidad

16

การใช้งานของ regexes ของ java พยายามจับคู่สตริงทั้งหมด

ที่แตกต่างจาก Perl Perex ซึ่งพยายามหาส่วนที่ตรงกัน

ถ้าคุณต้องการค้นหาสตริงที่ไม่มีอะไรนอกจากตัวอักษรพิมพ์เล็กให้ใช้รูปแบบ [a-z]+

หากคุณต้องการค้นหาสตริงที่มีอักขระตัวพิมพ์เล็กอย่างน้อยหนึ่งตัวให้ใช้รูปแบบ .*[a-z].*


ข้อมูลเพิ่มเติมได้ที่นี่
ycomp


12

มือสอง

String[] words = {"{apf","hum_","dkoe","12f"};
    for(String s:words)
    {
        if(s.matches("[a-z]+"))
        {
            System.out.println(s);
        }
    }

4

ฉันประสบปัญหาเดียวกันเมื่อ:

Pattern ptr = Pattern.compile("^[a-zA-Z][\\']?[a-zA-Z\\s]+$");

ล้มเหลวข้างต้น!

Pattern ptr = Pattern.compile("(^[a-zA-Z][\\']?[a-zA-Z\\s]+$)");

ทำงานข้างต้นที่มีรูปแบบภายในและ()


2

แสดงออกปกติของคุณ[a-z]ไม่ตรงกับdkoeตั้งแต่มันตรงกับสายยาว 1. [a-z]+บางสิ่งบางอย่างเช่นการใช้งาน


-1

คุณจะต้องจับภาพอย่างน้อยหนึ่ง()รูปแบบเพื่อจับคู่และรูปแบบที่ถูกต้องเช่นนี้:

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("(^[a-z]+$)"))
    {
        System.out.println(s);
    }
}

วงเล็บไม่เปลี่ยนแปลงอะไรเลย
Touniouk

@Touniouk โดยไม่ต้องวงเล็บmatchesไม่มีผลลัพธ์ใด ๆ
MohsenB

-3

คุณสามารถทำตัวพิมพ์เล็กและตัวพิมพ์เล็กของคุณโดยทำ:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.