Apakah maksud Anda ingin menemukan frasa dalam teks, di mana setiap frasa tersebut merupakan permutasi yang sah dari kata-kata dalam frasa yang diberikan?
Nietzche-jou
2
Saya meletakkan ini di sini karena tiga atau empat jawaban mengabaikannya. Lookahead tidak cocok dengan panjang yang sama untuk setiap klausa, kecuali jika diakhiri dengan $. Satu lookahead bisa cocok dengan empat karakter, dan 6. lainnya. Misalnya, (? = A *) (? = Aab) akan cocok dengan aabaaaaba
Zachary Vance
2
coba gunakan karakter "space" untuk operator "AND".
1 I'd like to match paragraphs of text.. 2. Berisi teks tidak sesuai pesanan . Nomor 1 terbuka untuk interpretasi. Nomor 2 dapat dilakukan dengan beberapa cara. Cara 1 (?:(?:(?(1)(?!))\b(phrase1)\b.*?|(?(2)(?!))\b(phrase2)\b.*?)){2}:, Cara 2: (?=.*\bphrase1\b)(?=.*\bphrase2\b)di mana dalam hal ini, pencocokan paragraf dalam kasus ini tidak ditentukan hingga definisi paragraf diformalkan.
Jawaban:
385
Gunakan ekspresi reguler yang tidak dikonsumsi.
Notasi khas (yaitu Perl / Java) adalah:
(?=expr)
Ini berarti " expr pertandingan tetapi setelah itu terus mencocokkan pada titik pertandingan asli."
Anda dapat melakukan sebanyak ini dari yang Anda inginkan, dan ini akan menjadi "dan." Contoh:
(?=match this expression)(?=match this too)(?=oh, and this)
Anda bahkan dapat menambahkan grup tangkap di dalam ekspresi non-konsumsi jika Anda perlu menyimpan beberapa data di dalamnya.
Harus disebutkan bahwa contoh khusus ini disebut pernyataan lookahead positif. Ini memiliki kegunaan lain selain "dan". Perhatikan bahwa teks tidak dikonsumsi.
strager
7
Menggunakan (? =) Seperti ini menghasilkan regex yang tidak pernah berhasil. Tapi itu adalah analog konjungsi ke |. OP salah dalam apa yang menurutnya akan menyelesaikan masalahnya.
Bisakah Anda menambahkan beberapa contoh mudah dalam kode perl dalam jawaban Anda?
Pithikos
343
Anda perlu menggunakan lookahead seperti yang dikatakan beberapa responden lain, tetapi lookahead harus memperhitungkan karakter lain antara kata target dan posisi pertandingan saat ini. Sebagai contoh:
(?=.*word1)(?=.*word2)(?=.*word3)
The .*di lookahead pertama memungkinkannya cocok dengan banyak karakter yang diperlukan sebelum sampai ke "word1". Kemudian posisi pertandingan diatur ulang dan lookahead kedua mencari "word2". Atur ulang lagi, dan bagian terakhir cocok dengan "word3"; karena ini adalah kata terakhir yang Anda periksa, tidak perlu dilihat, tetapi tidak sakit.
Untuk mencocokkan seluruh paragraf, Anda harus melabuhkan regex di kedua ujungnya dan menambahkan final .*untuk menggunakan karakter yang tersisa. Menggunakan notasi gaya Perl, itu akan menjadi:
/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m
Pengubah 'm' adalah untuk mode multline; itu memungkinkan ^dan $cocok di batas paragraf ("batas garis" di regex-spoke). Sangat penting dalam hal ini bahwa Anda tidak menggunakan pengubah 's', yang memungkinkan metacharacter titik mencocokkan baris baru serta semua karakter lainnya.
Terakhir, Anda ingin memastikan Anda mencocokkan seluruh kata dan bukan hanya fragmen kata yang lebih panjang, jadi Anda perlu menambahkan batas kata:
+1 untuk jawaban yang jelas dan berhasil menampilkan salah satu kegunaan terbaik untuk lookaheads (tidak seperti penggunaan seperti peretasan untuk menghitung persentase kecocokan kata sandi). :)
zx81
1
@Liam :. MySQL menggunakan rasa POSIX ERE, jadi tidak. Ini secara efektif mengorbankan fitur yang mendukung kinerja, yang tampaknya masuk akal bagi saya. Ada informasi lebih lanjut di sini .
Alan Moore
3
ganti .*dengan [\s\S]*dalam javascript jika Anda memiliki baris baru seperti .pada mesin regex javascript tidak cocok dengan baris baru dan tidak dapat dibuat dengan pengubah
Wesley Smith
41
Lihat contoh ini:
Kami memiliki 2 regexps A dan B dan kami ingin mencocokkan keduanya, jadi dalam pseudo-code tampilannya seperti ini:
pattern ="/A AND B/"
Itu dapat ditulis tanpa menggunakan operator DAN seperti ini:
Itu benar dalam hal logika formal, tetapi sama sekali tidak membantu di sini. Dalam regex, TIDAK bisa lebih sulit untuk diungkapkan daripada DAN.
Alan Moore
@marvin_dpr Ini bekerja untuk saya di CMake sedangkan saran lainnya (?=expr)tidak. Tampaknya tergantung pada implementasi.
Melebius
38
Tidak ^berarti "permulaan string" dalam sintaks regex?
Lambda Fairy
3
Dalam regex secara umum, ^negasi hanya pada awal kelas karakter. Kecuali CMake melakukan sesuatu yang sangat funky (sampai-sampai menyebut bahasa pencocokan pola mereka "regex" dapat dianggap menyesatkan atau salah). Saya menduga fakta bahwa itu berhasil untuk Anda adalah kecelakaan yang terisolasi.
tripleee
29
Anda dapat melakukannya dengan ekspresi reguler tetapi mungkin Anda menginginkan yang lain. Misalnya menggunakan beberapa regexp dan menggabungkannya dalam klausa if.
Anda dapat menghitung semua permutasi yang mungkin dengan regexp standar, seperti ini (cocok dengan a, b dan c dalam urutan apa pun):
(abc)|(bca)|(acb)|(bac)|(cab)|(cba)
Namun, ini membuat regexp yang sangat panjang dan mungkin tidak efisien, jika Anda memiliki lebih dari beberapa istilah.
Jika Anda menggunakan beberapa versi regexp yang diperluas, seperti Perl atau Java, mereka memiliki cara yang lebih baik untuk melakukan ini. Jawaban lain menyarankan menggunakan operasi lookahead positif.
Saya tidak berpikir pendekatan Anda lebih tidak efisien daripada 3 lookaheads dengan backtracking bencana mereka. Tentu ini lebih panjang untuk ditulis, tetapi perhatikan bahwa Anda dapat dengan mudah membuat polanya secara otomatis. Perhatikan bahwa Anda dapat meningkatkannya agar gagal lebih cepat a(bc|cb)|b(ac|ca)|c(ab|ba). Dan yang paling penting, Anda bisa menggunakannya dengan semua rasa regex.
Casimir et Hippolyte
27
Operator AND tersirat dalam sintaks RegExp.
Operator OR sebaliknya harus ditentukan dengan pipa.
RegExp berikut:
var re =/ab/;
berarti huruf aDAN surat itu b.
Ini juga berfungsi dengan grup:
var re =/(co)(de)/;
itu berarti grup coDAN grup de.
Mengganti (implisit) DAN dengan OR akan membutuhkan baris berikut:
Sayangnya, ini bukan yang diminta OP. Ini menemukan apa pun dalam urutan itu, sedangkan mereka menginginkannya dalam urutan apa pun. Lihatlah jawabannya dengan stackoverflow.com/users/20938/alan-moore di bawah ini yang mana yang benar.
JESii
1
@ YESUS terima kasih atas poin Anda, Anda benar dan saya salah paham dengan pertanyaan dari Hugoware, saya berfokus terutama pada kalimat pertamanya. Jawaban yang tepat adalah penggunaan yang tepat dari operator lookahead, seperti yang ditulis AlanMoore. Bagaimanapun saya pikir seseorang mungkin menganggap klarifikasi saya berguna, seperti yang telah dibatalkan, jadi saya tidak akan membuang semuanya. Salam.
Emanuele Del Grande
13
Apakah tidak mungkin dalam kasus Anda untuk melakukan DAN pada beberapa hasil yang cocok? dalam pseudocode
Saya berada dalam situasi di mana saya memiliki beberapa kode yang merupakan tabel data aturan, dengan string pencocokan pola regex tunggal untuk menguji validitas aturan. Pindah ke beberapa tes bukan sesuatu yang bisa saya lakukan dalam kasus saya, dan umumnya dalam kasus orang lain juga!
Alan Wolfe
11
Mengapa tidak menggunakan awk?
dengan awk regex AND, ATAU masalahnya sangat sederhana
Saya akan memberi Anda beberapa contoh praktis yang akan membuat segalanya menjadi lebih jelas bagi sebagian dari Anda. Sebagai contoh katakanlah kita memiliki tiga baris teks:
[12/Oct/2015:00:37:29+0200]// only this + will get selected[12/Oct/2015:00:37:x9 +0200][12/Oct/2015:00:37:29+020x]
Apa yang ingin kita lakukan di sini adalah memilih tanda + tetapi hanya jika setelah dua angka dengan spasi dan jika sebelum empat angka. Itulah satu-satunya kendala. Kami akan menggunakan ungkapan reguler ini untuk mencapainya:
'~(?<=\d{2} )\+(?=\d{4})~g'
Catatan jika Anda memisahkan ekspresi itu akan memberi Anda hasil yang berbeda.
Atau mungkin Anda ingin memilih beberapa teks di antara tag ... tetapi bukan tag! Maka Anda bisa menggunakan:
'~(?<=<p>).*?(?=<\/p>)~g'
untuk teks ini:
<p>Hello !</p><p>I wont select tags! Only text with in</p>
Jawaban mana yang merupakan jawaban yang diterima? Silakan tambahkan tautan ke sana untuk masa depan saya.
James Brown
6
Urutan selalu tersirat dalam struktur ekspresi reguler. Untuk mencapai yang Anda inginkan, Anda harus mencocokkan string input beberapa kali dengan ekspresi yang berbeda.
Apa yang ingin Anda lakukan tidak mungkin dengan regexp tunggal.
Secara teknis itu tidak mungkin, tetapi tidak layak untuk diterapkan. Saya tidak tahu mengapa seseorang turun jabatan ...
Robert P
13
Mungkin karena itu tidak hanya mungkin, itu sederhana, dengan asumsi rasa regex Anda mendukung lookaheads. Dan itu taruhan yang bagus; sebagian besar bahasa pemrograman utama saat ini mendukungnya.
Alan Moore
3
Gunakan DAN di luar ekspresi reguler. Dalam PHP lookahead operator sepertinya tidak bekerja untuk saya, saya malah menggunakan ini
I'd like to match paragraphs of text
.. 2. Berisi teks tidak sesuai pesanan . Nomor 1 terbuka untuk interpretasi. Nomor 2 dapat dilakukan dengan beberapa cara. Cara 1(?:(?:(?(1)(?!))\b(phrase1)\b.*?|(?(2)(?!))\b(phrase2)\b.*?)){2}
:, Cara 2:(?=.*\bphrase1\b)(?=.*\bphrase2\b)
di mana dalam hal ini, pencocokan paragraf dalam kasus ini tidak ditentukan hingga definisi paragraf diformalkan.Jawaban:
Gunakan ekspresi reguler yang tidak dikonsumsi.
Notasi khas (yaitu Perl / Java) adalah:
(?=
expr)
Ini berarti " expr pertandingan tetapi setelah itu terus mencocokkan pada titik pertandingan asli."
Anda dapat melakukan sebanyak ini dari yang Anda inginkan, dan ini akan menjadi "dan." Contoh:
(?=match this expression)(?=match this too)(?=oh, and this)
Anda bahkan dapat menambahkan grup tangkap di dalam ekspresi non-konsumsi jika Anda perlu menyimpan beberapa data di dalamnya.
sumber
Anda perlu menggunakan lookahead seperti yang dikatakan beberapa responden lain, tetapi lookahead harus memperhitungkan karakter lain antara kata target dan posisi pertandingan saat ini. Sebagai contoh:
The
.*
di lookahead pertama memungkinkannya cocok dengan banyak karakter yang diperlukan sebelum sampai ke "word1". Kemudian posisi pertandingan diatur ulang dan lookahead kedua mencari "word2". Atur ulang lagi, dan bagian terakhir cocok dengan "word3"; karena ini adalah kata terakhir yang Anda periksa, tidak perlu dilihat, tetapi tidak sakit.Untuk mencocokkan seluruh paragraf, Anda harus melabuhkan regex di kedua ujungnya dan menambahkan final
.*
untuk menggunakan karakter yang tersisa. Menggunakan notasi gaya Perl, itu akan menjadi:Pengubah 'm' adalah untuk mode multline; itu memungkinkan
^
dan$
cocok di batas paragraf ("batas garis" di regex-spoke). Sangat penting dalam hal ini bahwa Anda tidak menggunakan pengubah 's', yang memungkinkan metacharacter titik mencocokkan baris baru serta semua karakter lainnya.Terakhir, Anda ingin memastikan Anda mencocokkan seluruh kata dan bukan hanya fragmen kata yang lebih panjang, jadi Anda perlu menambahkan batas kata:
sumber
.*
dengan[\s\S]*
dalam javascript jika Anda memiliki baris baru seperti.
pada mesin regex javascript tidak cocok dengan baris baru dan tidak dapat dibuat dengan pengubahLihat contoh ini:
Kami memiliki 2 regexps A dan B dan kami ingin mencocokkan keduanya, jadi dalam pseudo-code tampilannya seperti ini:
Itu dapat ditulis tanpa menggunakan operator DAN seperti ini:
di PCRE:
sumber
(?=expr)
tidak. Tampaknya tergantung pada implementasi.^
berarti "permulaan string" dalam sintaks regex?^
negasi hanya pada awal kelas karakter. Kecuali CMake melakukan sesuatu yang sangat funky (sampai-sampai menyebut bahasa pencocokan pola mereka "regex" dapat dianggap menyesatkan atau salah). Saya menduga fakta bahwa itu berhasil untuk Anda adalah kecelakaan yang terisolasi.Anda dapat melakukannya dengan ekspresi reguler tetapi mungkin Anda menginginkan yang lain. Misalnya menggunakan beberapa regexp dan menggabungkannya dalam klausa if.
Anda dapat menghitung semua permutasi yang mungkin dengan regexp standar, seperti ini (cocok dengan a, b dan c dalam urutan apa pun):
Namun, ini membuat regexp yang sangat panjang dan mungkin tidak efisien, jika Anda memiliki lebih dari beberapa istilah.
Jika Anda menggunakan beberapa versi regexp yang diperluas, seperti Perl atau Java, mereka memiliki cara yang lebih baik untuk melakukan ini. Jawaban lain menyarankan menggunakan operasi lookahead positif.
sumber
a(bc|cb)|b(ac|ca)|c(ab|ba)
. Dan yang paling penting, Anda bisa menggunakannya dengan semua rasa regex.Operator AND tersirat dalam sintaks RegExp.
Operator OR sebaliknya harus ditentukan dengan pipa.
RegExp berikut:
berarti huruf
a
DAN surat itub
.Ini juga berfungsi dengan grup:
itu berarti grup
co
DAN grupde
.Mengganti (implisit) DAN dengan OR akan membutuhkan baris berikut:
sumber
Apakah tidak mungkin dalam kasus Anda untuk melakukan DAN pada beberapa hasil yang cocok? dalam pseudocode
sumber
Mengapa tidak menggunakan awk?
dengan awk regex AND, ATAU masalahnya sangat sederhana
sumber
Jika Anda menggunakan ekspresi reguler Perl, Anda dapat menggunakan tampilan positif:
Sebagai contoh
akan menjadi angka lebih besar dari 100 dan habis dibagi 5
sumber
Anda bisa menyalurkan output Anda ke regex lain. Menggunakan grep, Anda bisa melakukan ini:
grep A | grep B
sumber
Selain jawaban yang diterima
Saya akan memberi Anda beberapa contoh praktis yang akan membuat segalanya menjadi lebih jelas bagi sebagian dari Anda. Sebagai contoh katakanlah kita memiliki tiga baris teks:
Lihat demo di sini DEMO
Apa yang ingin kita lakukan di sini adalah memilih tanda + tetapi hanya jika setelah dua angka dengan spasi dan jika sebelum empat angka. Itulah satu-satunya kendala. Kami akan menggunakan ungkapan reguler ini untuk mencapainya:
Catatan jika Anda memisahkan ekspresi itu akan memberi Anda hasil yang berbeda.
Atau mungkin Anda ingin memilih beberapa teks di antara tag ... tetapi bukan tag! Maka Anda bisa menggunakan:
untuk teks ini:
Lihat demo di sini DEMO
sumber
Urutan selalu tersirat dalam struktur ekspresi reguler. Untuk mencapai yang Anda inginkan, Anda harus mencocokkan string input beberapa kali dengan ekspresi yang berbeda.
Apa yang ingin Anda lakukan tidak mungkin dengan regexp tunggal.
sumber
Gunakan DAN di luar ekspresi reguler. Dalam PHP lookahead operator sepertinya tidak bekerja untuk saya, saya malah menggunakan ini
Regex di atas akan cocok jika panjang kata sandi adalah 3 karakter atau lebih dan tidak ada spasi dalam kata sandi.
sumber