Regex: khớp với lần xuất hiện đầu tiên của nhân vật


358

Tôi đang tìm kiếm một mô hình phù hợp với tất cả mọi thứ cho đến khi xuất hiện lần đầu tiên của một nhân vật cụ thể, nói ";" - một dấu chấm phẩy .

Tôi đã viết điều này:

/^(.*);/

Nhưng nó thực sự phù hợp với tất cả mọi thứ (bao gồm cả dấu chấm phẩy) cho đến lần xuất hiện cuối cùng của dấu chấm phẩy.


65
/^(.*?);/cũng nên hoạt động (nó được gọi là không tham lam ), nhưng câu trả lời được đưa ra sử dụng [^;]*là tốt hơn.
Pascal

Làm thế nào bạn sẽ chọn tất cả mọi thứ, sau dấu chấm phẩy, và không phải dấu chấm phẩy.
Muhammad Umer

thấy điều này hoạt động \w+(?!([^]+;)|;)nhưng điều này không tại sao? .+(?!([^]+;)|;)
Muhammad Umer

1
Pascal, bạn nên viết nó như một câu trả lời!
Sean Kendle 17/8/2015

@Pascal Điều này phù hợp như câu trả lời! Cảm ơn!
neverMind9

Câu trả lời:


503

Bạn cần

/[^;]*/

Đây [^;]là một lớp nhân vật , nó phù hợp với tất cả mọi thứ trừ dấu chấm phẩy.

Để trích dẫn perlretrang này:

Bạn có thể chỉ định một lớp ký tự, bằng cách đính kèm một danh sách các ký tự trong [], sẽ khớp với bất kỳ ký tự nào trong danh sách. Nếu ký tự đầu tiên sau "[" là "^", lớp khớp với bất kỳ ký tự nào không có trong danh sách.

Điều này sẽ làm việc trong hầu hết các phương ngữ regex.


Điểm tuyệt vời của giải pháp này là cũng khớp với cuối dòng, ví dụ trong trường hợp của tôi, tôi đã có foo=bar;baz=bax;bab=bafvà nó phù hợp bab=bafngay cả khi không có ;Chính xác những gì tôi cần. Không chắc tại sao nó hoạt động mặc dù thông số kỹ thuật phù hợp với mọi thứ trừ biểu tượng mục tiêu ...
skryvets 16/12/19

303

Sẽ;

/^(.*?);/

công việc?

Đây ?là một toán tử lười biếng, vì vậy regex lấy càng ít càng tốt trước khi khớp với ;.


4
ya, nhưng sau khi mở rộng bicarbonate cho Tim Toady, tôi tin rằng các lớp nhân vật bị phủ định chiến thắng vì định lượng lười biếng bao gồm backtraking. +1 dù sao đi nữa.
Amarghosh

3
Đáng đọc về chủ đề hiệu suất: blog.stevenlevithan.com/archives/greedy-lazy-performance
Glenn Slaven

38

/^[^;]*/

[^;] Nói phù hợp với bất cứ điều gì ngoại trừ dấu chấm phẩy. Dấu ngoặc vuông là một toán tử khớp tập hợp, về cơ bản, khớp với bất kỳ ký tự nào trong bộ ký tự này, ^khi bắt đầu làm cho nó khớp với nhau, do đó, khớp bất kỳ thứ gì không có trong bộ này.


3
Xin lưu ý rằng ^ đầu tiên trong câu trả lời này mang lại cho regex một ý nghĩa hoàn toàn khác: Nó làm cho biểu thức chính quy chỉ tìm các kết quả bắt đầu từ đầu chuỗi. Trong trường hợp này, đó thực sự sẽ là một no-op nếu bạn chỉ chạy biểu thức chính quy một lần. Nếu bạn muốn tìm kiếm nhiều kết quả khớp trong một chuỗi, ^ đầu tiên sẽ phải đi.
Dan Breslau

4
Anh ấy đã nói rằng anh ấy muốn khớp mọi thứ cho đến khi xuất hiện dấu chấm phẩy đầu tiên, vì vậy tôi cho rằng anh ấy có ý nghĩa từ đầu chuỗi.
Glenn Slaven



8

văn bản mẫu:

"this is a test sentence; to prove this regex; that is g;iven below"

Ví dụ: nếu chúng tôi có văn bản mẫu ở trên, regex /(.*?\;)/sẽ cung cấp cho bạn mọi thứ cho đến khi xuất hiện lần đầu tiên của dấu chấm phẩy ( ;), bao gồm cả dấu chấm phẩy:"this is a test sentence;"


3
Không cần thiết phải thoát ;char vì nó không phải là nhân vật đặc biệt. Nhóm ()cũng không bắt buộc. Bạn có thể đi với/.*?;/
Aliaksei Kliuchnikau

1
vâng, bạn hoàn toàn đúng việc trốn thoát giống như "an toàn hơn là xin lỗi"
poncius

2
Đây là câu trả lời tôi đang tìm kiếm. Nên ? làm cho trận đấu kết thúc ở lần xuất hiện đầu tiên? Tên của tài sản này ... (hãy gọi nó là) thuộc tính của regex là gì?
Parziphal

1
@Parziphal ?nhân vật làm cho trận đấu trở nên lười biếng (khớp càng nhiều lần càng tốt). Hãy nghĩ về các ký tự khớp với biểu thức cho đến dấu chấm phẩy đầu tiên sau đó nó sẽ không đi xa hơn vì nó từ bỏ (lười biếng;))
derekantrican

5

đây không phải là một giải pháp regex, nhưng một cái gì đó đủ đơn giản để mô tả vấn đề của bạn. Chỉ cần tách chuỗi của bạn và nhận mục đầu tiên từ mảng của bạn.

$str = "match everything until first ; blah ; blah end ";
$s = explode(";",$str,2);
print $s[0];

đầu ra

$ php test.php
match everything until first

5

Điều này rất hữu ích cho tôi khi tôi đang cố gắng tìm ra cách khớp tất cả các ký tự trong thẻ xml bao gồm các thuộc tính. Tôi đã chạy vào vấn đề "khớp mọi thứ đến cùng" với:

/<simpleChoice.*>/

nhưng đã có thể giải quyết vấn đề với:

/<simpleChoice[^>]*>/

sau khi đọc bài này Cảm ơn tất cả.


1
Tôi đã nhận thấy rằng việc phân tích cú pháp thực sự hiệu quả hơn (mỗi ngôn ngữ hoặc khung có các lớp riêng cho điều đó) html / xml vì định dạng máy của nó, regex dành cho ngôn ngữ tự nhiên.
Leon Fedotov

1
Đẹp. Tôi đã sử dụng điều này để sửa các tài liệu xml có lỗi cú pháp trong <!DOCTYPE>thẻ. Vì trình phân tích cú pháp không thể xử lý nó.
Martin Schneider

5

Điều này sẽ khớp với lần xuất hiện đầu tiên chỉ trong mỗi chuỗi và sẽ bỏ qua các lần xuất hiện tiếp theo.

/^([^;]*);*/

3

"/^([^\/]*)\/$/" làm việc cho tôi, để chỉ nhận các "thư mục" hàng đầu từ một mảng như:

a/   <- this
a/b/
c/   <- this
c/d/
/d/e/
f/   <- this

2

Thực sự hơi buồn khi không ai cho bạn câu trả lời đúng ....

Trong regex ,? làm cho nó không tham lam. Theo mặc định, regex sẽ khớp nhiều nhất có thể (tham lam)

Đơn giản chỉ cần thêm một? và nó sẽ không tham lam và phù hợp với ít nhất có thể!

Chúc may mắn, hy vọng rằng sẽ giúp.


3
Điều này phụ thuộc rất nhiều vào việc thực hiện regex thực tế và không phải mọi triển khai đều có chế độ không tham lam.
karatedog

0

Tôi thấy rằng

/^[^,]*,/

hoạt động tốt

',' là "dấu phân cách" ở đây.

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.