Regex không hoạt động trong String.matches ()


147

Tôi có đoạn mã nhỏ này

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

Giả sử in

dkoe

nhưng nó không in gì cả !!


41
Java matchesđặt một ^ khi bắt đầu và $ ở cuối regexes cho bạn. Vì vậy, matches("[a-z]")thực sự sẽ tìm kiếm / ^ [az] $ / thay vào đó.
Robino

Có @Robino bạn hoàn toàn đúng.
Mihir

1
Chắc chắn, nếu bạn mong đợi matchestìm kiếm bất kỳ sự xuất hiện của [a-z], thì nó nên phù hợp với tất cả? Tôi sẽ không mong đợi matcheskiểm tra từng nhân vật theo từng biểu thức.
PhilHibbs

@Robino: Chức năng đó được mô tả / ghi lại ở đâu?
Toru

@Toru Trên trang tài liệu java cho String.Matches - còn ở đâu nữa? Một Google thông thường về "chuỗi java khớp với tài liệu" tiết lộ, trong kết quả hàng đầu, cụm từ "str.matches (regex) mang lại kết quả chính xác như biểu thức". Từ quan trọng là "chính xác".
Robino

Câu trả lời:


323

Chào mừng bạn đến với .matches()phương thức đặt tên sai của Java ... Nó cố gắng và khớp với TẤT CẢ đầu vào. Thật không may, các ngôn ngữ khác đã theo sau :(

Nếu bạn muốn xem regex có khớp với văn bản đầu vào hay không, hãy sử dụng a Pattern, a Matcher.find()phương thức của công cụ đối sánh:

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

Nếu những gì bạn muốn thực sự là để xem liệu đầu vào chỉ có chữ thường, bạn có thể sử dụng .matches(), nhưng bạn cần khớp một hoặc nhiều ký tự: nối thêm một +lớp ký tự của bạn, như trong [a-z]+. Hoặc sử dụng ^[a-z]+$.find().


2
tôi tìm thấy 100 năm hướng dẫn không đầy đủ trực tuyến. Không thể tìm thấy một cái tốt. Bạn có đề nghị nào không?
Giăng

Thanx @fge để giải thích .matches(). Có thể bạn biết tại sao .find()làm việc rất chậm trong ví dụ này ?
Konstantin Konopko

3
Bạn có ý nghĩa gì bởi các ngôn ngữ khác theo sau phù hợp ? Từ những gì tôi biết, chỉ có C ++ có một bộ phương thức tương đương - regex_searchregex_match. Trong Python, re.matchchỉ neo các kết quả khớp ở đầu chuỗi (như thể nó là vậy \Apattern) và Python 3.x đã có một .fullmatch()phương thức hay. Trong JS, Go, PHP và .NET, không có phương thức regex nào neo hoàn toàn khớp. Mặc định, Tìm kiếm đàn hồi, Lược đồ XML và HTML5 / Trình xác thực Các mẫu Angluar luôn được neo theo mặc định. Trong Swift / Objective C, có một cách để neo mẫu khi bắt đầu với một tùy chọn.
Wiktor Stribiż

Có một cách oneliner để làm điều này?
Đức Hồng Y - Phục hồi Monica

44

[a-z]khớp với một char duy nhất giữa a và z. Vì vậy, nếu chuỗi của bạn chỉ là "d", ví dụ, thì nó sẽ khớp và được in ra.

Bạn cần thay đổi regex của mình [a-z]+để khớp với một hoặc nhiều ký tự.


12
Tất nhiên, nó phù hợp với một char duy nhất, đó là những gì regrec làm! Tuy nhiên, điều không rõ ràng (và cũng không nên xảy ra!) Là java đặt tiền tố ^và hậu tố $xung quanh biểu thức chính được cung cấp, thay đổi nó một cách không mong muốn và tạo ra các lỗi lạ. Họ không nên làm điều đó, bởi vì đó không phải là ý nghĩa của biểu thức chính quy.
klaar

28

String.matchestrả về cho dù toàn bộ chuỗi phù hợp với regex, không chỉ bất kỳ chuỗi con nào.


3
Một cái gì đó thực sự là một thực tế đáng buồn là bạn đúng. Tôi thực sự không biết tại sao họ lại làm theo cách này.
Hola Soy Edu Feliz Navidad

16

Việc triển khai regexes của java cố gắng khớp với toàn bộ chuỗi

khác với perex regexes, chúng cố gắng tìm một phần phù hợp

nếu bạn muốn tìm một chuỗi không có gì ngoài các ký tự chữ thường, hãy sử dụng mẫu [a-z]+

nếu bạn muốn tìm một chuỗi chứa ít nhất một ký tự chữ thường, hãy sử dụng mẫu .*[a-z].*


thêm thông tin ở đây
ycomp

3
Tại sao điều này không được ghi nhận ?!
Leo Orientis

12

Đã sử dụng

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

4

Tôi đã từng đối mặt với cùng một vấn đề:

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

Những điều trên thất bại!

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

Ở trên đã làm việc với mô hình trong ().


2

Biểu thức thông thường của bạn [a-z]không khớp dkoevì nó chỉ khớp với Chuỗi chiều dài 1. Sử dụng một cái gì đó như [a-z]+.


-1

bạn phải đặt ít nhất một bản chụp ()trong mẫu để khớp và mẫu chính xác như thế này:

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

Chân đế không thay đổi bất cứ điều gì.
Touniouk

@Touniouk không có ngoặc matcheskhông có đầu ra.
MohsenB

-3

Bạn có thể làm cho trường hợp mẫu của bạn không nhạy cảm bằng cách làm:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.