Regex untuk string yang tidak diakhiri dengan akhiran yang diberikan


190

Saya belum dapat menemukan regex yang tepat untuk mencocokkan string apa pun yang tidak berakhir dengan kondisi tertentu. Misalnya, saya tidak ingin mencocokkan apa pun yang berakhir dengan a.

Ini cocok

b
ab
1

Ini tidak cocok

a
ba

Saya tahu regex harus diakhiri dengan $untuk menandai akhirnya, meskipun saya tidak tahu apa yang harus mendahuluinya.

Sunting : Pertanyaan aslinya sepertinya bukan contoh yang sah untuk kasus saya. Jadi: bagaimana menangani lebih dari satu karakter? Katakan sesuatu yang tidak berakhir dengan ab?

Saya sudah bisa memperbaikinya, menggunakan utas ini :

.*(?:(?!ab).).$

Meskipun downside dengan ini, itu tidak cocok dengan satu karakter.


5
Ini bukan duplikat dari pertanyaan terkait - pencocokan hanya dengan akhir membutuhkan sintaks yang berbeda dari pencocokan di mana saja dalam string. Lihat saja jawaban teratas di sini.
Jaustin

Saya setuju, ini bukan duplikat dari pertanyaan terkait. Saya ingin tahu bagaimana kita dapat menghapus "tanda" di atas?
Alan Cabrera

Tidak ada tautan yang bisa saya lihat.
Alan Cabrera

Jawaban:


252

Anda tidak memberi kami bahasa, tetapi jika dukungan rasa regex Anda melihat di belakang pernyataan , inilah yang Anda butuhkan:

.*(?<!a)$

(?<!a)adalah tampilan yang dinegasikan di belakang pernyataan yang memastikan, bahwa sebelum akhir string (atau baris dengan mpengubah), tidak ada karakter "a".

Lihat di sini di Regexr

Anda juga dapat dengan mudah memperluas ini dengan karakter lain, karena ini memeriksa string dan bukan kelas karakter.

.*(?<!ab)$

Ini akan cocok dengan apa pun yang tidak berakhir dengan "ab", lihat di Regexr


1
Saya tidak tahu RegexPAL, tetapi regex berbeda dalam semua bahasa dan melihat di belakang pernyataan adalah fitur lanjutan yang tidak didukung oleh semua.
stema

7
regexpal adalah regex tester dan javascript berbasis javascript tidak mendukung pernyataan yang terlihat menyedihkan
HamZa

Lookbehinds tidak didukung di regexr (javascript)
Stealth Rabbi

1
Kurangnya tampilan di JS membuat saya menangis. Jika Anda melakukan sisi server meskipun Anda mungkin dapat menggunakan modul PCRE di NPM atau serupa untuk menggunakannya secara langsung (ini adalah set binding jadi saya tidak berpikir Anda dapat menggunakannya di muka)
Eirik Birkeland

Lebih banyak jenis pernyataan lookahead / lookbehind: stackoverflow.com/q/2973436/12484
Jon Schneider

76

Gunakan simbol not ( ^):

.*[^a]$

Jika Anda meletakkan ^simbol di awal tanda kurung, itu berarti "segala sesuatu kecuali benda-benda di dalam tanda kurung." $hanyalah sebuah jangkar sampai akhir.

Untuk beberapa karakter , cukup letakkan semuanya dalam rangkaian karakter mereka sendiri:

.*[^a][^b]$

1
+1, dengan peringatan bahwa ini tidak cocok dengan string kosong (yang mungkin atau mungkin tidak seperti yang dimaksudkan), jadi artinya agak "karakter apa pun yang tidak ada dalam tanda kurung".
Fred Foo

3
@ 0A0D: string yang mengandung spasi bukan string kosong.
Fred Foo

7
@ 0A0D Sebenarnya, itu tidak cocok untuk diperdebatkan, itu fakta
tckmn

8
@ Doorknob: itu tidak cocok aeatau cb.
Fred Foo

1
Tidak, ini tidak akan mengizinkan "acb" juga.
Menno

49

Untuk mencari file yang tidak diakhiri dengan ".tmp" kami menggunakan regex berikut:

^(?!.*[.]tmp$).*$

Diuji dengan Regex Tester memberikan hasil sebagai berikut:

masukkan deskripsi gambar di sini


1
Ini menarik, ada ide mengapa ini berhasil dan mengapa ^.*(?![.]tmp$)tidak?
Łukasz Zaroda

4
Awal .*Anda sudah cocok dengan seluruh string, sehingga pengecualian yang tersisa tidak berfungsi lagi.
FiveO

Untuk tujuan saya, ini berhasil dan jawaban lainnya tidak. Terima kasih!
David Moritz

8
.*[^a]$

regex di atas akan cocok dengan string yang tidak berakhir dengan a.


Saya telah memperpanjang pertanyaan saya karena contoh aslinya tampaknya tidak sepenuhnya cocok dengan kasus saya. Bisakah kamu menyelesaikannya?
Menno

5

Coba ini

/.*[^a]$/

Yang []menunjukkan kelas karakter, dan ^membalikkan kelas karakter untuk mencocokkan segalanya kecuali sebuah a.


1

Pertanyaannya sudah lama tetapi saya tidak dapat menemukan solusi yang lebih baik yang saya posting di sini. Temukan semua drive USB tetapi tidak mencantumkan partisi , sehingga menghapus "bagian [0-9]" dari hasil. Saya akhirnya melakukan dua grep, yang terakhir meniadakan hasilnya:

ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -vE "part[0-9]*$"

Ini hasil pada sistem saya:

pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0

Jika saya hanya ingin partisi yang bisa saya lakukan:

ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -E "part[0-9]*$"

Di mana saya mendapatkan:

pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part1
pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part2

Dan ketika saya melakukannya:

readlink -f /dev/disk/by-path/pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0

Saya mendapat:

/dev/sdb

1

Jawaban yang diterima baik-baik saja jika Anda dapat menggunakan lookaround. Namun, ada juga pendekatan lain untuk menyelesaikan masalah ini.

Jika kita melihat regex yang diusulkan secara luas untuk pertanyaan ini:

.*[^a]$

Kami akan menemukan bahwa itu hampir berhasil. Itu tidak menerima string kosong, yang mungkin sedikit tidak nyaman. Namun, ini adalah masalah kecil ketika berhadapan dengan hanya satu karakter. Namun, jika kita ingin mengecualikan seluruh string, mis. "Abc", maka:

.*[^a][^b][^c]$

tidak akan melakukannya. Itu tidak akan menerima ac, misalnya.

Namun ada solusi mudah untuk masalah ini. Kita bisa mengatakan:

.{,2}$|.*[^a][^b][^c]$

atau versi yang lebih umum:

.{,n-1}$|.*[^firstchar][^secondchar]$ di mana n adalah panjang string yang Anda inginkan melarang (untuk abcitu 3), dan firstchar, secondchar, ... yang pertama, karakter kedua ... n dari string (untuk abcitu akan menjadi a, kemudian b, kemudian c).

Ini berasal dari pengamatan sederhana bahwa string yang lebih pendek dari teks yang tidak akan kami larang tidak dapat memuat teks ini menurut definisi. Jadi kita bisa menerima apa pun yang lebih pendek ("ab" bukan "abc"), atau apa pun yang cukup lama untuk kita terima tetapi tanpa akhir.

Berikut ini contoh menemukan yang akan menghapus semua file yang bukan .jpg:

find . -regex '.{,3}$|.*[^.][^j][^p][^g]$' -delete


.{,2}$|.*[^a][^b][^c]$tidak cocokccc
psalaets

0

Apa pun yang cocok sesuatu yang berakhir dengan --- .*a$Jadi, ketika Anda cocok regex, meniadakan kondisi atau alternatifnya Anda juga dapat melakukan .*[^a]$di mana [^a]sarana apa saja yangnot a


0

Jika Anda menggunakan grepatau sedsintaks akan sedikit berbeda. Perhatikan bahwa [^a][^b]metode sekuensial tidak berfungsi di sini:

balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n'
jd8a
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a]$"
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^b]$"
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^c]$"
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c]$"
jd8a
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c^a]$"

FWIW, saya menemukan hasil yang sama di Regex101 , yang saya pikir adalah sintaksis JavaScript.

Buruk: https://regex101.com/r/MJGAmX/2
Bagus: https://regex101.com/r/LzrIBu/2

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.