Regex, String.matches () içinde çalışmaz


148

Bu küçük kod parçasına sahibim

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

Yazdırılması gerekiyordu

dkoe

ama hiçbir şey yazdırmıyor !!


41
Java matches, sizin için normal ifadelerin başına ^ ve sonuna $ koyar. Yani matches("[a-z]")aslında / ^ [az] $ / arayacak.
Robino

Evet @Robino kesinlikle haklısınız.
Mihir

1
Elbette, matchesherhangi bir oluşumunu aramayı bekliyorsanız , hepsiyle [a-z]eşleşmeli mi? matchesHer karakteri tek tek normal ifadeyle karşılaştırmayı beklemem .
PhilHibbs

@Robino: Bu işlevsellik nerede tanımlanıyor / belgeleniyor?
Toru

@Toru String.Matches için java dokümanları sayfasında - başka nerede? Sıradan bir Google "java dizesi belgelerle eşleşir", en üstteki sonuçta "str.matches (regex) ifadesi ile tam olarak aynı sonucu verir" ifadesini ortaya çıkarır. Önemli kelime "aynen" dir.
Robino

Yanıtlar:


329

Java'nın yanlış adlandırılmış .matches()yöntemine hoş geldiniz ... TÜM girdileri dener ve eşleştirir. Ne yazık ki, diğer diller de aynı şeyi yaptı :(

Normal ifadenin bir giriş metniyle eşleşip eşleşmediğini görmek istiyorsanız, a Pattern, a Matcherve .find()eşleştirici yöntemini kullanın :

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

İstediğiniz şey gerçekten bir girdinin yalnızca küçük harflere sahip olup olmadığını görmekse, kullanabilirsiniz .matches(), ancak bir veya daha fazla karakteri eşleştirmeniz gerekir: 'deki +gibi karakter sınıfınıza a ekleyin [a-z]+. Veya ^[a-z]+$ve kullanın .find().


2
İnternette 100'lerce eksik öğretici buluyorum. İyi bir tane bulamadım. Önerin var mı?
John

Açıklamak için teşekkürler @fge .matches(). Bu örnekte neden .find()bu kadar yavaş çalıştığını biliyor musunuz ?
Konstantin Konopko

3
Diğer dillerin uyması derken ne demek istiyorsun ? Bildiğim kadarıyla, yalnızca C ++ 'ın eşdeğer bir yöntem kümesi vardır - regex_searchve regex_match. Python'da, re.matcheşleşmeyi yalnızca dizenin başlangıcına sabitler ( \Apatternöyleymiş gibi ) ve Python 3.x'in güzel bir .fullmatch()yöntemi vardır. JS, Go, PHP ve .NET'te, eşleşmeyi örtük olarak sabitleyen regex yöntemleri yoktur. ElasticSearch, XML Schema ve HTML5 / Validators Angluar kalıpları her zaman varsayılan olarak sabitlenir. Swift / Objective C'de, modeli başlangıçta bir seçenekle sabitlemenin bir yolu var.
Wiktor Stribiżew

Bunu yapmanın tek bir yolu var mı?
Kardinal - Monica'yı eski

Eğer regex nesi merak saat atık ve zaten ... uzun zaman önce upvoted ettik fark bu SO cevap yukarıda sona erdiği duygu
matewka

45

[a-z]a ve z arasındaki tek bir karakterle eşleşir . Yani, "d"örneğin dizeniz sadece olsaydı, eşleşirdi ve yazdırılırdı.

Normal ifadenizi [a-z]+bir veya daha fazla karakterle eşleşecek şekilde değiştirmeniz gerekir .


13
Tabii ki tek bir karakterle eşleşiyor, bu normal ifadenin yaptığı şey! Ancak açık olmayan (ve durum böyle olmamalıdır!) Java'nın öneki ^ve soneki $sağlanan regexp'in etrafına koyması, istemeden değiştirmesi ve garip hatalar yaratmasıdır. Bunu yapmamalılar çünkü ilk normal ifadenin kastettiği bu değildi.
klaar

30

String.matchesdizenin tamamının herhangi bir alt dizeyle değil, normal ifadeyle eşleşip eşleşmediğini döndürür .


3
Gerçekten üzücü olan bir şey, haklı olmanızdır. Bunu neden böyle yaptıklarını gerçekten bilmiyorum.
Hola Soy Edu Feliz Navidad

16

Java'nın normal ifadeler uygulaması tüm dizeyle eşleşmeye çalışır

bu, eşleşen bir bölümü bulmaya çalışan perl normal ifadelerinden farklıdır.

küçük harf karakterlerinden başka hiçbir şey içermeyen bir dize bulmak istiyorsanız, kalıbı kullanın [a-z]+

en az bir küçük harf içeren bir dize bulmak istiyorsanız, kalıbı kullanın .*[a-z].*


daha fazla bilgi burada
ycomp

3
Bu neden belgelenmedi ?
Leo Orientis

13

Kullanılmış

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

4

Aynı problemle bir kez karşılaştım:

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

Yukarıdakiler başarısız oldu!

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

Yukarıdakiler (ve içindeki desenle çalıştı ).


2

Normal ifadeniz [a-z]uymuyor dkoeyalnızca gibi uzunluğu 1. Kullanım şeyin Dizeleri maçları beri [a-z]+.


-1

Eşleşmek ()için desene en azından bir yakalama koymalı ve aşağıdaki gibi düzeltmelisiniz:

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

Parantezler hiçbir şeyi değiştirmedi.
Touniouk

@Touniouk'un parantez olmadan matchesherhangi bir çıktısı yoktur.
MohsenB

-3

Aşağıdakileri yaparak deseninizin büyük / küçük harf duyarlı olmasını sağlayabilirsiniz:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.