Regex - cara mencocokkan semuanya kecuali pola tertentu


Jawaban:


192

Anda bisa menggunakan pernyataan harapan di masa depan:

(?!999)\d{3}

Contoh ini cocok dengan tiga digit selain 999.


Tetapi jika Anda tidak memiliki implementasi ekspresi reguler dengan fitur ini (lihat Perbandingan Rasa Ekspresi Reguler ), Anda mungkin harus membuat ekspresi reguler dengan fitur dasar sendiri.

Ekspresi reguler yang kompatibel hanya dengan sintaks dasar adalah:

[0-8]\d\d|\d[0-8]\d|\d\d[0-8]

Ini juga cocok dengan urutan tiga digit yang tidak 999.


1
Lihat-depan bukan sintaks ekspresi reguler standar, itu adalah ekstensi Perl, itu hanya akan bekerja di Perl, PCRE (Perl-Compatible RegEx) atau implementasi non-standar lainnya
Juliano

10
Ini mungkin tidak standar, tetapi tidakkah sebagian besar bahasa modern mendukungnya? Bahasa apa yang tidak mendukung pandangan maju hari ini?
Bryan Oakley

1
Itu benar. Tetapi kebanyakan rasa regex mendukung fitur ini (lihat < regular-expressions.info/refflavors.html> ).
Gumbo

1
saya pikir regex terakhir juga tidak akan cocok dengan 009, 019 ... dll
Sebastian Viereck

1
Lex standar untuk C tidak menggunakan PCRE :-(
pieman72

30

Jika Anda ingin mencocokkan kata A dalam string dan tidak cocok dengan kata B. Misalnya: Jika Anda memiliki teks:

1. I have a two pets - dog and a cat
2. I have a pet - dog

Jika Anda ingin mencari baris teks yang MEMILIKI anjing untuk hewan peliharaan dan TIDAK kucing, Anda dapat menggunakan ekspresi reguler ini:

^(?=.*?\bdog\b)((?!cat).)*$

Ini hanya akan menemukan baris kedua:

2. I have a pet - dog

Dia gagal menyebutkannya dalam pertanyaan, tetapi OP sebenarnya menggunakan findstrperintah DOS . Itu hanya memberikan sebagian kecil dari kemampuan yang Anda harapkan untuk ditemukan di alat regex; lookahead tidak ada di antara mereka. (Saya baru saja menambahkan tag findstr sendiri.)
Alan Moore

2
hm, ya, saya temukan sekarang di salah satu komentarnya di posting. Saya melihat Regex di judulnya. Bagaimanapun, jika seseorang menemukan posting ini ketika mencari yang sama untuk ekspresi reguler, seperti yang saya lakukan, mungkin itu bisa membantu seseorang :) terima kasih atas komentar
Aleks

15

Cocokkan dengan pola dan gunakan bahasa host untuk membalikkan hasil boolean dari pertandingan. Ini akan jauh lebih mudah dibaca dan dipelihara.


1
Kemudian saya berakhir dengan (~ A atau B) alih-alih (A dan ~ B). Itu tidak menyelesaikan masalah saya.
notnot

1
Pseudo-code: String toTest; if (toTest.matches (A) AND! toTest.matches (B)) {...}
Ben S

Saya seharusnya lebih jelas - potongannya tidak sepenuhnya independen. Jika A cocok dengan bagian dari string, maka kami peduli jika ~ B cocok dengan sisanya (tetapi tidak harus semuanya). Ini adalah untuk fungsi findstr baris perintah windows, yang saya temukan dibatasi untuk regexs benar, jadi titik diperdebatkan.
notnot

8

tidak, menghidupkan kembali pertanyaan kuno ini karena ada solusi sederhana yang tidak disebutkan. (Temukan pertanyaan Anda saat melakukan riset untuk pencarian karunia regex .)

Saya dihadapkan pada situasi di mana saya harus mencocokkan pola (A dan ~ B).

Regex dasar untuk ini sangat sederhana: B|(A)

Anda mengabaikan pertandingan keseluruhan dan memeriksa tangkapan Grup 1, yang akan berisi A.

Contoh (dengan semua penafian tentang parsing html di regex): A adalah digit, B adalah digit di dalam <a tag

Regex: <a.*?<\/a>|(\d+)

Demo (lihat Grup 1 di panel kanan bawah)

Referensi

Cara mencocokkan pola kecuali dalam situasi s1, s2, s3

Cara mencocokkan suatu pola kecuali ...


Ini kedengarannya terlalu bagus untuk menjadi kenyataan! Sayangnya, solusi ini tidak universal dan gagal di Emacs, bahkan setelah diganti \ddengan [[:digit:]]. Referensi pertama menyebutkan itu khusus untuk Perl dan PHP: "Ada variasi menggunakan sintaks khusus untuk Perl dan PHP yang mencapai hal yang sama."
miguelmorin

4

Pelengkap bahasa biasa juga merupakan bahasa biasa, tetapi untuk mengkonstruksinya Anda harus membuat DFA untuk bahasa biasa, dan membuat perubahan status yang valid menjadi kesalahan. Lihat ini sebagai contoh. Apa halaman tidak katakan adalah bahwa itu dikonversi /(ac|bd)/menjadi /(a[^c]?|b[^d]?|[^ab])/. Konversi dari DFA kembali ke ekspresi reguler tidak sepele. Lebih mudah jika Anda dapat menggunakan ekspresi reguler tidak berubah dan mengubah semantik dalam kode, seperti yang disarankan sebelumnya.


2
Jika saya berurusan dengan regex yang sebenarnya maka ini semua akan diperdebatkan. Regex sekarang tampaknya merujuk pada ruang pencocokan pola CSG-ish (?) Samar-samar yang didukung sebagian besar bahasa. Karena saya harus mencocokkan (A dan ~ B), tidak ada cara untuk menghapus negasi dan masih melakukan semuanya dalam satu langkah.
notnot

Lookahead, seperti yang dijelaskan di atas, akan melakukannya jika findstr melakukan sesuatu di luar regangan DFA yang sebenarnya. Semuanya agak aneh dan saya tidak tahu mengapa saya harus melakukan gaya command-line (batch sekarang) ini. Ini hanyalah contoh lain dari tangan saya diikat.
notnot

1
@notnot: Anda menggunakan findstr dari Windows? Maka Anda hanya perlu / v. Seperti: findstr A inputfile | findstr / v B> outputfile.txt Yang pertama cocok dengan semua baris dengan A, yang kedua cocok dengan semua baris yang tidak memiliki B.
Juliano

Terima kasih! Sebenarnya itulah yang saya butuhkan. Saya tidak mengajukan pertanyaan seperti itu, jadi saya masih memberikan jawaban kepada Gumbo untuk jawaban yang lebih umum.
notnot

1

pola - ulang

str.split(/re/g) 

akan mengembalikan semuanya kecuali polanya.

Tes di sini


Anda mungkin ingin menyebutkan bahwa Anda harus bergabung lagi.
tomdemuyt

Pendekatan serupa menggunakan replace str.replace(/re/g, ''), maka tidak perlu bergabung kembali dengan mereka. juga jika Anda melempar trailing yang bagus? seperti str.replace(/\re\s?/g, '')kemudian Anda menyingkirkan duplikat spasi yang Anda miliki dari sesuatu yang diganti di tengah-tengah string
jakecraige

0

Jawaban saya di sini mungkin bisa menyelesaikan masalah Anda juga:

https://stackoverflow.com/a/27967674/543814

  • Alih-alih Ganti, Anda akan menggunakan Pertandingan.
  • Alih-alih grup $1, Anda akan membaca grup $2.
  • Grup $2dibuat tidak menangkap di sana, yang akan Anda hindari.

Contoh:

Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");

Grup penangkapan pertama menentukan pola yang ingin Anda hindari. Grup menangkap terakhir menangkap yang lainnya. Cukup baca grup itu $2,.


0
(B)|(A)

lalu gunakan tangkapan kelompok 2 apa ...


Dia perlu menangkap bukan B, ia bertujuan bukan hanya mengabaikan semua pola B.
hexicle
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.