Regex lookahead, lookbehind dan atomic group

314

Saya menemukan hal-hal ini di tubuh regex saya tetapi saya tidak tahu apa yang bisa saya gunakan untuk itu. Apakah ada yang punya contoh sehingga saya bisa mencoba memahami cara kerjanya?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group
Spidfire
sumber
18
Mengapa situs web regex tidak memiliki tabel sederhana seperti ini? Sebagai gantinya mereka hanya memiliki blok teks yang menjelaskan. regular-expressions.info/lookaround.html
Whitecat
3
@Whitecat Coba: regex101.com regexr.com
Andrew

Jawaban:

852

Contohnya

Diberikan string foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

Anda juga dapat menggabungkannya:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

Definisi

Lihat ke depan positif (?=)

Temukan ekspresi A di mana ekspresi B berikut:

A(?=B)

Lihat negatif di depan (?!)

Temukan ekspresi A di mana ekspresi B tidak mengikuti:

A(?!B)

Lihat di belakang positif (?<=)

Temukan ekspresi A di mana ekspresi B mendahului:

(?<=B)A

Lihat di belakang negatif (?<!)

Temukan ekspresi A di mana ekspresi B tidak mendahului:

(?<!B)A

Kelompok atom (?>)

Grup atom keluar dari grup dan membuang pola-pola alternatif setelah pola pertama yang cocok di dalam grup (pengulangan mundur dinonaktifkan).

  • (?>foo|foot)sditerapkan untuk footsakan cocok dengan alternatif pertama foo, lalu gagal karena stidak segera mengikuti, dan berhenti karena pengulangan mundur dinonaktifkan

Grup non-atomik akan memungkinkan mundurnya; jika pencocokan berikutnya gagal, maka akan mundur dan menggunakan pola alternatif sampai kecocokan untuk seluruh ekspresi ditemukan atau semua kemungkinan habis.

  • (foo|foot)sditerapkan untuk footsakan:

    1. cocok dengan alternatif pertama foo, lalu gagal karena stidak segera mengikuti foots, dan mundur ke alternatif kedua;
    2. cocok dengan alternatif ke-2 foot, lalu berhasil dengan ssegera mengikuti foots, dan berhenti.

Beberapa sumber daya

Penguji online

kaki langit
sumber
1
Apa yang Anda maksud dengan bagian "temukan bar kedua"? Hanya ada satu bilah di ekspresi / string. Terima kasih
ziggy
2
@ziggy string yang diuji adalah "foobarbarfoo". Seperti yang Anda lihat ada dua foo dan dua bar di string.
skyfoot
4
Adakah yang bisa menjelaskan kapan seseorang membutuhkan kelompok atom? Jika saya hanya perlu mencocokkan dengan alternatif pertama, mengapa saya ingin memberikan beberapa alternatif?
arviman
2
Penjelasan yang lebih baik tentang grup atom pada jawaban ini . Dapatkah seseorang mengedit di sini untuk menyelesaikan jawaban didatik ini?
Peter Krauss
5
Hanya catatan bahwa jawaban ini sangat penting ketika saya berakhir pada sebuah proyek yang membutuhkan daging regex serius. Ini adalah penjelasan yang sangat baik, ringkas tentang melihat-lihat.
Tom Coughlin
215

Penelusuran adalah pernyataan lebar nol. Mereka memeriksa regex (ke kanan atau kiri dari posisi saat ini - berdasarkan depan atau belakang), berhasil atau gagal ketika kecocokan ditemukan (berdasarkan apakah itu positif atau negatif) dan membuang bagian yang cocok. Mereka tidak mengkonsumsi karakter apa pun - pencocokan untuk regex yang mengikuti mereka (jika ada), akan mulai pada posisi kursor yang sama.

Baca regular-expression.info untuk lebih jelasnya.

  • Penampilan positif:

Sintaksis:

(?=REGEX_1)REGEX_2

Cocokkan hanya jika REGEX_1 cocok; setelah mencocokkan REGEX_1, kecocokan dibuang dan mencari REGEX_2 dimulai pada posisi yang sama.

contoh:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 adalah [a-z0-9]{4}$yang cocok dengan empat karakter alfanumerik yang diikuti dengan akhir baris.
REGEX_2 [a-z]{1,2}[0-9]{2,3}cocok dengan satu atau dua huruf diikuti oleh dua atau tiga digit.

REGEX_1 memastikan bahwa panjang string memang 4, tetapi tidak mengkonsumsi karakter apa pun sehingga pencarian REGEX_2 dimulai di lokasi yang sama. Sekarang REGEX_2 memastikan bahwa string tersebut cocok dengan beberapa aturan lain. Tanpa melihat ke depan itu akan cocok dengan string dengan panjang tiga atau lima.

  • Melihat ke arah negatif

Sintaksis:

(?!REGEX_1)REGEX_2

Cocokkan hanya jika REGEX_1 tidak cocok; setelah memeriksa REGEX_1, pencarian untuk REGEX_2 dimulai pada posisi yang sama.

contoh:

(?!.*\bFWORD\b)\w{10,30}$

Bagian lihat-depan memeriksa FWORDdalam string dan gagal jika menemukannya. Jika tidak menemukan FWORD, lihat-depan berhasil dan bagian berikut memverifikasi bahwa panjang string adalah antara 10 dan 30 dan itu hanya berisi karakter kataa-zA-Z0-9_

Lihat-belakang mirip dengan melihat-depan: itu hanya melihat di belakang posisi kursor saat ini. Beberapa rasa regex seperti javascript tidak mendukung pernyataan di belakang. Dan sebagian besar rasa yang mendukungnya (PHP, Python, dll) mengharuskan bagian yang terlihat di belakang itu memiliki panjang yang tetap.

  • Grup atom pada dasarnya membuang / lupa token berikutnya dalam grup setelah token cocok. Periksa halaman ini untuk contoh-contoh kelompok atom
Amarghosh
sumber
mengikuti penjelasan Anda, tampaknya tidak berfungsi dalam javascript, /(?=source)hello/.exec("source...hummhellosource ") = null. Apakah penjelasan Anda benar?
Helin Wang
@HelinWang Penjelasan itu benar. Regex Anda mengharapkan string yang merupakan sumber dan sekaligus halo!
Amarghosh
@ jddxf Ingin menguraikan?
Amarghosh
@Amarghosh Saya setuju dengan "Mereka memeriksa regex (ke kanan atau kiri dari posisi saat ini - berdasarkan depan atau belakang), berhasil atau gagal ketika pertandingan ditemukan (berdasarkan apakah itu positif atau negatif) dan membuang yang cocok bagian.". Jadi lookahead harus memeriksa regex ke kanan posisi saat ini dan sintaks dari lookahead positif harus x (? = Y)
jddxf
@Amarghosh (?=REGEX_1)REGEX_2hanya akan cocok jika REGEX_2datang setelah REGEX_1 ?
aandis
0

Mencari-cari dengan cepat.
Bagaimana membedakan lookahead dan lookbehind? Ikuti tur 2 menit dengan saya:

(?=) - positive lookahead
(?<=) - positive lookbehind

Seharusnya

    A  B  C #in a line

Sekarang, kami bertanya B, Di mana Anda?
B memiliki dua solusi untuk menyatakan lokasi itu:

Satu, B memiliki A di depan dan memiliki C bebind
Dua, B di depan (lookahead) dari C dan di belakang (lookhehind) A.

Seperti yang bisa kita lihat, bagian belakang dan depan berlawanan dalam dua solusi.
Regex adalah solusi Dua.

Kalkulus
sumber