Regex tidak berfungsi di String.matches ()

147

Saya punya sepotong kecil kode ini

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

Seharusnya mencetak

dkoe

tetapi tidak mencetak apa-apa !!

John
sumber
41
Java matchesmenempatkan ^ di awal dan $ di akhir regex untuk Anda. Jadi matches("[a-z]")sebenarnya akan mencari / ^ [az] $ / sebagai gantinya.
Robino
Ya, @Robino Anda memang benar.
Mihir
1
Tentunya, jika Anda berharap matchesuntuk mencari kejadian [a-z], maka itu harus cocok dengan mereka semua? Saya tidak akan berharap matchesuntuk memeriksa setiap karakter secara individual terhadap regex.
PhilHibbs
@Robino: Di manakah fungsionalitas itu dijelaskan / didokumentasikan?
Toru
@ Toru Di halaman java docs untuk String.Matches - di mana lagi? Google biasa "dokumentasi string java cocok" mengungkapkan, di hasil atas, frasa "str.matches (regex) menghasilkan hasil yang persis sama dengan ekspresi". Kata yang penting adalah "tepat".
Robino

Jawaban:

323

Selamat datang di .matches()metode Java yang salah nama ... Mencoba dan cocok dengan SEMUA input. Sayangnya, bahasa lain mengikuti :(

Jika Anda ingin melihat apakah regex cocok dengan teks input, gunakan a Pattern, a Matcherdan .find()metode korek api :

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

Jika yang Anda inginkan adalah untuk melihat apakah input hanya memiliki huruf kecil, Anda dapat menggunakan .matches(), tetapi Anda harus mencocokkan satu atau lebih karakter: tambahkan a +ke kelas karakter Anda, seperti pada [a-z]+. Atau gunakan ^[a-z]+$dan .find().

Fge
sumber
2
saya menemukan 100-an tutorial online tidak lengkap. Tidak dapat menemukan yang bagus. Apakah Anda punya saran?
John
Thanx @fge untuk menjelaskan .matches(). Mungkin Anda tahu mengapa .find()kerjanya sangat lambat dalam contoh ini ?
Konstantin Konopko
3
Apa yang Anda maksud dengan bahasa lain yang mengikuti ? Dari yang saya tahu, hanya C ++ yang memiliki seperangkat metode - regex_searchdan regex_match. Dalam Python, re.matchhanya jangkar yang cocok di awal string (seolah-olah itu \Apattern) dan Python 3.x telah mendapatkan .fullmatch()metode yang bagus . Di JS, Go, PHP, dan .NET, tidak ada metode regex yang mengaitkan pertandingan secara implisit. ElasticSearch, Schema XML dan HTML5 / Validators Pola Angluar selalu berlabuh secara default. Di Swift / Objective C, ada cara untuk menahan pola di awal dengan sebuah opsi.
Wiktor Stribiżew
Apakah ada cara oneliner untuk melakukan ini?
Cardinal - Reinstate Monica
44

[a-z]cocok dengan satu char antara a dan z. Jadi, jika string Anda hanya "d", misalnya, maka itu akan cocok dan dicetak.

Anda perlu mengubah regex Anda [a-z]+agar cocok dengan satu atau lebih karakter.

dogbane
sumber
12
Tentu saja itu cocok dengan satu char, itulah yang regexp lakukan! Namun yang tidak jelas (dan tidak seharusnya demikian!) Adalah bahwa java menempatkan awalan ^dan akhiran di $sekitar regexp yang disediakan, mengubahnya secara tidak diinginkan dan membuat bug aneh. Mereka seharusnya tidak melakukan itu, karena bukan itu maksud regexp awal.
klaar
28

String.matchesmengembalikan apakah seluruh string cocok dengan regex, bukan sembarang substring.

yshavit
sumber
3
Sesuatu yang benar-benar kenyataan yang menyedihkan adalah Anda benar. Saya benar-benar tidak tahu mengapa mereka melakukannya dengan cara ini.
Hola Soy Edu Feliz Navidad
16

Implementasi java dari regex mencoba untuk mencocokkan keseluruhan string

itu berbeda dari perl regex, yang mencoba menemukan bagian yang cocok

jika Anda ingin menemukan string dengan karakter huruf kecil, gunakan pola [a-z]+

jika Anda ingin menemukan string yang mengandung setidaknya satu karakter huruf kecil, gunakan pola .*[a-z].*

Hachi
sumber
info lebih lanjut di sini
ycomp
3
Mengapa ini tidak didokumentasikan ?!
Leo Orientis
12

Bekas

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

Saya pernah menghadapi masalah yang sama:

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

Di atas gagal!

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

Di atas bekerja dengan pola di dalam (dan ).

Shanta
sumber
2

Ekspresi reguler Anda [a-z]tidak cocok dkoekarena hanya cocok dengan string panjang 1. Gunakan sesuatu seperti [a-z]+.


sumber
-1

Anda harus memasukkan setidaknya satu tangkapan ()dalam pola untuk dicocokkan, dan memperbaiki pola seperti ini:

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("(^[a-z]+$)"))
    {
        System.out.println(s);
    }
}
MohsenB
sumber
Kurung tidak mengubah apa pun.
Touniouk
@ Touniouk tanpa tanda kurung matchestidak memiliki output.
MohsenB
-3

Anda dapat membuat pola huruf Anda tidak sensitif dengan melakukan:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
Anita Kulkarni
sumber