Làm thế nào để khớp bất cứ thứ gì cho đến khi chuỗi ký tự này trong một biểu thức chính quy?


514

Lấy biểu thức chính quy này : /^[^abc]/. Điều này sẽ khớp với bất kỳ ký tự đơn nào ở đầu chuỗi, ngoại trừ a, b hoặc c.

Nếu bạn thêm một dấu *sau - /^[^abc]*/- biểu thức chính quy sẽ tiếp tục thêm từng ký tự tiếp theo vào kết quả, cho đến khi nó gặp một a, hoặc b , hoặc c .

Ví dụ, với chuỗi nguồn "qwerty qwerty whatever abc hello", biểu thức sẽ khớp với "qwerty qwerty wh".

Nhưng nếu tôi muốn chuỗi phù hợp là "qwerty qwerty whatever "

... Nói cách khác, làm thế nào tôi có thể khớp mọi thứ với (nhưng không bao gồm) trình tự chính xác "abc" ?


Bạn có ý nghĩa match but not includinggì?
Toto

5
Ý tôi là tôi muốn khớp "qwerty qwerty whatever "- không bao gồm "abc". Nói cách khác, tôi không muốn kết quả phù hợp "qwerty qwerty whatever abc".
callum

2
Trong javascript bạn có thể chỉ cần do string.split('abc')[0]. Chắc chắn không phải là một câu trả lời chính thức cho vấn đề này, nhưng tôi thấy nó đơn giản hơn regex.
Wylliam Judd

Câu trả lời:


1021

Bạn đã không chỉ định hương vị của regex nào bạn đang sử dụng, nhưng điều này sẽ hoạt động trong bất kỳ loại phổ biến nhất nào có thể được coi là "hoàn thành".

/.+?(?=abc)/

Làm thế nào nó hoạt động

Một .+? phần là phiên bản không tham lam của .+ (một hoặc nhiều thứ). Khi chúng ta sử dụng .+, động cơ về cơ bản sẽ phù hợp với mọi thứ. Sau đó, nếu có một cái gì đó khác trong regex, nó sẽ quay lại trong các bước cố gắng khớp với phần sau. Đây là hành vi tham lam , có nghĩa là càng nhiều càng tốt để thỏa mãn .

Khi sử dụng .+?, thay vì khớp tất cả cùng một lúc và quay lại các điều kiện khác (nếu có), động cơ sẽ khớp các ký tự tiếp theo theo từng bước cho đến khi phần tiếp theo của regex được khớp (một lần nữa nếu có). Đây là sự không tham lam , có nghĩa là phù hợp với ít nhất có thể để đáp ứng .

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

Theo đó chúng tôi có , một khẳng định chiều rộng bằng không , một cái nhìn xung quanh . Cấu trúc được nhóm này khớp với nội dung của nó, nhưng không được tính là các ký tự trùng khớp ( độ rộng bằng không ). Nó chỉ trả về nếu nó phù hợp hay không ( khẳng định ).(?={contents})

Vì vậy, trong các điều khoản khác, regex /.+?(?=abc)/có nghĩa là:

Ghép bất kỳ ký tự nào càng ít càng tốt cho đến khi tìm thấy "abc", mà không tính "abc".


12
Điều này có thể sẽ không hoạt động với ngắt dòng, nếu chúng được cho là bị bắt.
einord

3
Sự khác biệt giữa .+?và là .*gì?
robbie

4
@ robbie0630 +có nghĩa là 1 hoặc nhiều hơn, trong đó *có nghĩa là 0 trở lên. Việc bao gồm / loại trừ ?sẽ làm cho nó tham lam hoặc không tham lam.
jinglểula

2
@ testsjoe2 /.+?(?=abc|xyz)/
JohnWlingsby

4
Tôi đã nhận thấy rằng điều này không chọn được bất cứ điều gì nếu mẫu bạn đang tìm kiếm không tồn tại, thay vào đó nếu bạn sử dụng, ^(?:(?!abc)(?!def).)*bạn có thể xâu chuỗi để loại trừ các mẫu bạn không muốn và nó vẫn sẽ lấy mọi thứ khi cần ngay cả khi mẫu không tồn tại
Karan Shishoo

122

Nếu bạn đang tìm cách nắm bắt mọi thứ lên đến "abc":

/^(.*?)abc/

Giải trình:

( )nắm bắt những biểu hiện bên trong dấu ngoặc đơn để truy cập sử dụng $1, $2vv

^ bắt đầu trận đấu

.*phù hợp với bất cứ điều gì, ?không tham lam (phù hợp với số lượng ký tự tối thiểu được yêu cầu) - [1]

[1] Lý do tại sao điều này là cần thiết là vì nếu không, trong chuỗi sau:

whatever whatever something abc something abc

theo mặc định, regexes là tham lam , có nghĩa là nó sẽ phù hợp nhất có thể. Vì vậy, /^.*abc/sẽ phù hợp với "bất cứ điều gì abc một cái gì đó". Thêm bộ định lượng không tham lam ?làm cho regex chỉ khớp với "bất cứ thứ gì".


4
Cảm ơn, nhưng cái của bạn không bao gồm abc trong trận đấu. Nói cách khác, kết quả khớp là "bất cứ thứ gì abc".
callum

1
Bạn có thể giải thích những gì cuối cùng bạn đang cố gắng làm? Nếu kịch bản của bạn là: (A) Bạn muốn có được mọi thứ dẫn đến "abc" - chỉ cần sử dụng dấu ngoặc đơn xung quanh những gì bạn muốn nắm bắt. (B) Bạn muốn khớp chuỗi với "abc" - dù sao bạn cũng phải kiểm tra abc, vì vậy nó cần phải là một phần của biểu thức chính quy bất kể. Làm thế nào khác bạn có thể kiểm tra rằng nó ở đó?
Jared Ng

seddường như không hỗ trợ kết hợp không tham lam, cũng không hỗ trợ nhìn xung quanh ( (?=...)). Tôi có thể làm gì nữa? Lệnh ví dụ: echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"trả về two,three, FOUR FIVE, nhưng tôi mong đợi two,three...
CodeManX

1
@CoDEmanX Có lẽ bạn nên đăng câu hỏi đó dưới dạng câu hỏi riêng của bạn chứ không phải là một bình luận, đặc biệt là vì nó đặc biệt về sed. Điều đó đang được nói, để giải quyết câu hỏi của bạn: bạn có thể muốn xem câu trả lời cho câu hỏi này . Cũng lưu ý rằng trong ví dụ của bạn, một thông dịch viên không tham lam sẽ trở lại two, không two,three.
Jared Ng

3
Đây là cách MỌI câu trả lời regex nên nhìn - ví dụ và giải thích về tất cả các phần ...
jave.web

54

Như @Jared Ng và @Issun đã chỉ ra, chìa khóa để giải quyết loại RegEx này như "khớp mọi thứ với một từ hoặc chuỗi con nhất định" hoặc "khớp mọi thứ sau một từ hoặc chuỗi con nhất định" được gọi là các xác nhận có độ dài bằng 0 . Đọc thêm về chúng ở đây.

Trong trường hợp cụ thể của bạn, nó có thể được giải quyết bằng một cái nhìn tích cực phía trước: .+?(?=abc)

Một bưc tranh đang gia ngan lơi noi. Xem giải thích chi tiết trong ảnh chụp màn hình.

Ảnh chụp màn hình Regex101


23
.+?(?=abc)regex sao chép có giá trị hơn.
Tom

Điều gì về việc loại trừ không gian hàng đầu?
Royi

8

Những gì bạn cần là nhìn xung quanh khẳng định như thế nào .+? (?=abc).

Xem: Các xác nhận không có độ dài của Lookahead và Lookbehind

Hãy lưu ý rằng điều đó [abc]không giống như abc. Bên trong ngoặc không phải là một chuỗi - mỗi ký tự chỉ là một trong những khả năng. Bên ngoài dấu ngoặc nó trở thành chuỗi.


7

Đối với regex trong Java và tôi cũng tin vào hầu hết các công cụ regex, nếu bạn muốn bao gồm phần cuối cùng thì điều này sẽ hoạt động:

.+?(abc)

Ví dụ: trong dòng này:

I have this very nice senabctence

chọn tất cả các ký tự cho đến khi "abc" và cũng bao gồm abc

sử dụng regex của chúng tôi, kết quả sẽ là: I have this very nice senabc

Kiểm tra điều này: https://regex101.com/r/mX51ru/1


4

Tôi đã kết thúc câu hỏi stackoverflow này sau khi tìm kiếm trợ giúp để giải quyết vấn đề của mình nhưng không tìm thấy giải pháp nào cho nó :(

Vì vậy, tôi đã phải ứng biến ... sau một thời gian tôi đã xoay sở để đạt được regex tôi cần:

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy, tôi cần tối đa một thư mục trước thư mục "grp-bps", mà không bao gồm dấu gạch ngang cuối cùng. Và nó được yêu cầu phải có ít nhất một thư mục sau thư mục "grp-bps".

Biên tập

Phiên bản văn bản để sao chép-dán (thay đổi 'grp-bps' cho văn bản của bạn):

.*\/grp-bps\/[^\/]+

6
Không có phiên bản văn bản? 🙄
kiradotee

2

Điều này sẽ có ý nghĩa về regex.

  1. Từ chính xác có thể nhận được từ lệnh regex sau:

("(. *?)") / G

Ở đây, chúng ta có thể có được từ chính xác trên toàn cầu, thuộc về dấu ngoặc kép. Ví dụ: Nếu văn bản tìm kiếm của chúng tôi là,

Đây là ví dụ cho các từ "trích dẫn kép"

sau đó chúng ta sẽ nhận được "trích dẫn kép" từ câu đó.


Chào mừng bạn đến với StackOverflow và cảm ơn bạn đã cố gắng giúp đỡ. Tuy nhiên, tôi thấy rất khó để thấy điều này giúp mục tiêu được nêu trong câu hỏi. Bạn có thể xây dựng? Bạn có thể áp dụng nó cho các ví dụ nhất định? Bạn dường như tập trung vào việc xử lý ", mà đối với tôi dường như không liên quan đến câu hỏi.
Yunnosch

1
Xin chào, tôi đã giải thích làm thế nào để có được từ hoặc câu ở giữa các ký tự đặc biệt. Ở đây câu hỏi của chúng tôi cũng là "bất cứ điều gì cho đến khi chuỗi các ký tự đặc biệt". Vì vậy, tôi đã cố gắng với dấu ngoặc kép và giải thích nó ở đây. Cảm ơn.
Ponmurugan Mohanraj

2

Trên con trăn:

.+?(?=abc) làm việc cho trường hợp dòng đơn.

[^]+?(?=abc)không hoạt động, vì python không nhận ra [^] là regex hợp lệ. Để làm cho kết hợp nhiều dòng hoạt động, bạn sẽ cần sử dụng tùy chọn re.DOTALL, ví dụ:

re.findall('.+?(?=abc)', data, re.DOTALL)

0

Tôi tin rằng bạn cần subexpressions. Nếu tôi nhớ đúng, bạn có thể sử dụng ()dấu ngoặc bình thường cho biểu hiện phụ.

Phần này là từ hướng dẫn grep:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

Làm một cái gì đó như ^[^(abc)]nên làm các thủ thuật.


Xin lỗi, điều đó không hiệu quả. Đặt abc trong ngoặc đơn dường như không tạo ra sự khác biệt nào. Chúng vẫn được coi là "a OR b OR c".
callum

-1

Các $đánh dấu sự kết thúc của một chuỗi, do đó một cái gì đó như thế này nên làm việc: [[^abc]*]$nơi bạn đang tìm kiếm bất cứ điều gì không tận cùng bằng bất cứ lặp đi lặp lại của abc, nhưng nó sẽ phải ở cuối

Ngoài ra, nếu bạn đang sử dụng ngôn ngữ kịch bản với regex (như php hoặc js), chúng có chức năng tìm kiếm dừng khi lần đầu tiên gặp một mẫu (và bạn có thể chỉ định bắt đầu từ bên trái hoặc bắt đầu từ bên phải hoặc với php, bạn có thể thực hiện một hàm để phản chiếu chuỗi).


-6

thử cái này

.+?efg

Truy vấn :

select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;

đầu ra:

hijklmn
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.