Cocokkan semuanya kecuali string tertentu

119

Saya tahu bahwa regex berikut akan cocok dengan "merah", "hijau", atau "biru".

red|green|blue

Apakah ada cara mudah untuk membuatnya cocok dengan semuanya kecuali beberapa string tertentu?

Alfred
sumber
1
Tidak semua jenis ekspresi reguler dapat melakukan ini. Di lingkungan apa Anda bekerja? Jawa? Perl? .BERSIH? Beberapa pustaka regex C / C ++? Sebuah RDBMS?
FrustratedWithFormsDesigner
8
Anda tidak mengatakan apa yang Anda inginkan, tetapi Anda bisa membalikkan pengertian operasi "cocok". Ini tidak akan membantu Anda jika Anda mencoba melakukan ekstraksi pada bagian yang tidak cocok, tetapi untuk menguji apakah string yang dikecualikan tidak ada, itu akan berfungsi: if (!s.match(/red|green|blue/)) ... Catatan: Saya tahu bahwa OP tidak menentukan bahasa / kerangka kerja apa, jadi pendahuluan harus dianggap sebagai contoh umum, bukan yang preskriptif.
tvanfosson

Jawaban:

154

Jika Anda ingin memastikan bahwa stringnya bukan merah, hijau atau biru, jawabannya adalah caskey. Namun, yang sering diinginkan adalah memastikan bahwa garis tersebut tidak mengandung merah, hijau atau biru di mana pun di dalamnya. Untuk itu, tandai ekspresi reguler dengan ^dan sertakan .*dalam lookahead negatif:

^(?!.*(red|green|blue))

Selain itu, anggap Anda menginginkan baris yang berisi kata "mesin" tetapi tanpa salah satu dari warna tersebut:

^(?!.*(red|green|blue)).*engine

Anda mungkin mengira Anda dapat memfaktorkan .*ke kepala dari ekspresi reguler:

^.*(?!red|green|blue)engine     # Does not work

tapi kamu tidak bisa. Anda harus memiliki kedua contoh .*agar berfungsi.

Wayne Conrad
sumber
48

Tergantung pada bahasanya, tetapi umumnya ada pernyataan negatif yang dapat Anda masukkan seperti ini:

(?!red|green|blue)

(Terima kasih atas perbaikan sintaksnya, di atas adalah Java dan Perl yang valid, YMMV)

caskey
sumber
2
@caskey, Jawaban lengkapnya adalah kombinasi saya dan Anda. Jika Anda ingin menggabungkannya, saya akan menghapus milik saya.
Wayne Conrad
14
Jawaban ini akan jauh lebih berguna jika Anda menjelaskannya sedikit. Misalnya: What do "?" dan "!" berarti? Mengapa Anda membutuhkan grup tangkap?
Lii
Itu juga Python yang valid.
Joe Mornin
baru saja menggunakan ini dengan pustaka regEx Delphi dan hanya bekerja seperti ini: ^ (?! merah | hijau | biru). Juga benar untuk mengujinya di regex101.com . Jadi, apakah kesalahan ketik di atas kehilangan ^ atau apakah sebenarnya berfungsi seperti itu di Java / Perl / Python ..?
Peter
33

Mencocokkan Apa Pun kecuali String yang Diberikan

Jika Anda ingin mencocokkan seluruh string di mana Anda ingin mencocokkan semuanya kecuali string tertentu, Anda dapat melakukannya seperti ini:

^(?!(red|green|blue)$).*$

Ini mengatakan, memulai pertandingan dari awal string di mana ia tidak bisa dimulai dan diakhiri dengan warna merah, hijau, atau biru dan cocokkan yang lain sampai akhir string.

Anda dapat mencobanya di sini: https://regex101.com/r/rMbYHz/2

Perhatikan bahwa ini hanya berfungsi dengan mesin regex yang mendukung tampilan negatif .

Sam
sumber
23

Anda tidak membutuhkan pandangan negatif. Ada contoh yang berfungsi:

/([\s\S]*?)(red|green|blue|)/g

Deskripsi:

  • [\s\S] - cocok dengan karakter apapun
  • * - pertandingan dari 0 hingga tidak terbatas dari grup sebelumnya
  • ? - cocokkan sesedikit mungkin
  • (red|green|blue|) - cocokkan salah satu kata ini atau tidak sama sekali
  • g - pola ulangi

Contoh:

whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

Akan:

whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

Menguji: regex101.com

hlcs
sumber
4
Anda dapat secara drastis mengurangi jumlah langkah dengan menukar [\ s \ S] dengan titik. Saya sangat bingung mengapa tampaknya setiap contoh lain menangkap setiap kata secara individual. Cara ini merupakan langkah-langkah yang sedikit lebih regex tetapi membutuhkan lebih sedikit pemrosesan pasca.
Zatronium
3
tetapi ini tidak melakukan pencocokan (validasi teks), ini hanya menghapus teks tertentu selama substitusi.
Marek R
Solusi ini tidak akan mengeluarkan potongan teks terakhir setelah kata-kata yang diketahui. Jadi, tidak perlu membandingkan kecepatan, itu salah saja.
Wiktor Stribiżew
@ WiktorStribew diperbaiki.
hlcs
10

Saya memiliki pertanyaan yang sama, solusi yang diusulkan hampir berfungsi tetapi mereka memiliki beberapa masalah. Pada akhirnya regex yang saya gunakan adalah:

^(?!red|green|blue).*

Saya mengujinya di Javascript dan .NET.

. * tidak boleh ditempatkan di dalam lookahead negatif seperti ini: ^ (?!. * red | green | blue) atau itu akan membuat elemen pertama berperilaku berbeda dari yang lain (yaitu "anotherred" tidak akan dicocokkan sementara " lain hijau "akan)

Durden81
sumber
3

Mencocokkan teks apa pun tetapi yang cocok dengan pola biasanya dicapai dengan memisahkan string dengan pola ekspresi reguler .

Contoh :

  • - Regex.Split(text, @"red|green|blue")atau, untuk menghilangkan nilai kosong, Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(lihat demo )
  • - Regex.Split(text, "red|green|blue")atau, untuk menghapus item kosong, Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(lihat demo , atau demo ini di mana LINQ didukung)
  • - text.split(/red|green|blue/)(tidak perlu menggunakan gpengubah di sini!) (untuk menghilangkan nilai kosong, gunakan text.split(/red|green|blue/).filter(Boolean)), lihat demo
  • - text.split("red|green|blue"), atau - untuk menyimpan semua sisa item kosong - gunakan text.split("red|green|blue", -1), atau untuk menghapus semua item kosong gunakan lebih banyak kode untuk menghapusnya (lihat demo )
  • - Mirip dengan Java`` text.split(/red|green|blue/)untuk mendapatkan semua item yang tertinggal, gunakan text.split(/red|green|blue/, -1)dan untuk menghapus semua item kosong, gunakan text.split(/red|green|blue/).findAll {it != ""})(lihat demo )
  • - text.split(Regex("red|green|blue"))atau, untuk menghapus item kosong, gunakan text.split(Regex("red|green|blue")).filter{ !it.isBlank() }, lihat demo
  • - text.split("red|green|blue"), atau untuk menyimpan semua sisa barang kosong, gunakan text.split("red|green|blue", -1)dan untuk menghapus semua barang kosong, gunakan text.split("red|green|blue").filter(_.nonEmpty)(lihat demo )
  • - text.split(/red|green|blue/), untuk menghilangkan nilai-nilai kosong gunakan .split(/red|green|blue/).reject(&:empty?)(dan untuk mendapatkan kedua item kosong di depan dan di belakang, gunakan -1sebagai argumen kedua, .split(/red|green|blue/, -1)) (lihat demo )
  • - my @result1 = split /red|green|blue/, $text;, atau dengan semua item kosong tertinggal my @result2 = split /red|green|blue/, $text, -1;,, atau tanpa item kosong, my @result3 = grep { /\S/ } split /red|green|blue/, $text;(lihat demo )
  • - preg_split('~red|green|blue~', $text)atau preg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)untuk mengeluarkan item kosong (lihat demo )
  • - re.split(r'red|green|blue', text)atau, untuk menghapus item kosong, list(filter(None, re.split(r'red|green|blue', text)))(lihat demo )
  • - Gunakan regexp.MustCompile("red|green|blue").Split(text, -1), dan jika Anda perlu menghapus item kosong, gunakan kode ini . Lihat Go demo .

CATATAN : Jika pola Anda berisi grup penangkapan , fungsi / metode pemisahan ekspresi reguler mungkin berperilaku berbeda, juga bergantung pada opsi tambahan. Silakan merujuk ke dokumentasi metode pemisahan yang sesuai kemudian.

Wiktor Stribiżew
sumber
0

Semua kecuali kata "merah"

var href = '(text-1) (red) (text-3) (text-4) (text-5)';

var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Semua kecuali kata "merah"

var href = '(text-1) (frede) (text-3) (text-4) (text-5)';

var test = href.replace(/\(([\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = p1.replace(/red/g, '');
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Юрий Светлов
sumber