Saya mengalami sedikit kesulitan membuat Python regex berfungsi saat mencocokkan dengan teks yang mencakup banyak baris. Contoh teksnya adalah ('\ n' adalah baris baru)
some Varying TEXT\n
\n
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n
[more of the above, ending with a newline]\n
[yep, there is a variable number of lines here]\n
\n
(repeat the above a few hundred times).
Saya ingin menangkap dua hal: bagian 'some_Varying_TEXT', dan semua baris teks huruf besar yang muncul dua baris di bawahnya dalam satu tangkapan (saya bisa menghapus karakter baris baru nanti). Saya sudah mencoba dengan beberapa pendekatan:
re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts
re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines
dan banyak variasinya tidak berhasil. Yang terakhir sepertinya cocok dengan baris teks satu per satu, yang sebenarnya bukan yang saya inginkan. Saya bisa menangkap bagian pertama, tidak masalah, tapi sepertinya saya tidak bisa menangkap 4-5 baris teks huruf besar. Saya ingin match.group (1) menjadi some_Varying_Text dan group (2) menjadi baris1 + baris2 + baris3 + dll sampai baris kosong ditemukan.
Jika ada yang penasaran, itu seharusnya urutan asam amino yang membentuk protein.
>
karakter utama . Haruskah itu?Jawaban:
Coba ini:
Saya pikir masalah terbesar Anda adalah Anda mengharapkan
^
dan$
anchor cocok dengan linefeeds, tetapi ternyata tidak. Dalam mode multiline,^
cocokkan posisi tepat setelah baris baru dan$
cocok dengan posisi tepat sebelum baris baru.Berhati-hatilah juga, bahwa baris baru dapat terdiri dari satu baris (\ n), carriage-return (\ r), atau carriage-return + linefeed (\ r \ n). Jika Anda tidak yakin bahwa teks target Anda hanya menggunakan umpan baris, Anda harus menggunakan versi regex yang lebih inklusif ini:
BTW, Anda tidak ingin menggunakan pengubah DOTALL di sini; Anda mengandalkan fakta bahwa titik tersebut cocok dengan segala sesuatu kecuali baris baru.
sumber
Ini akan berhasil:
Beberapa penjelasan tentang ekspresi reguler ini mungkin berguna:
^(.+?)\n\n((?:[A-Z]+\n)+)
^
) berarti "dimulai dari awal baris". Ketahuilah bahwa ini tidak cocok dengan baris baru itu sendiri (sama untuk $: artinya "tepat sebelum baris baru", tetapi tidak cocok dengan baris baru itu sendiri).(.+?)\n\n
berarti "cocokkan sesedikit mungkin karakter (semua karakter diperbolehkan) sampai Anda mencapai dua baris baru". Hasilnya (tanpa baris baru) dimasukkan ke dalam kelompok pertama.[A-Z]+\n
berarti "cocokkan sebanyak mungkin huruf besar sampai Anda mencapai baris baru. Ini mendefinisikan apa yang akan saya sebut baris teks .((?:
textline)+)
berarti mencocokkan satu atau lebih baris teks tetapi tidak menempatkan setiap baris dalam satu kelompok. Sebaliknya, letakkan semua baris teks dalam satu grup.\n
dalam ekspresi reguler jika Anda ingin menerapkan baris baru ganda di akhir.\n
atau\r
atau\r\n
) maka perbaiki ekspresi reguler dengan mengganti setiap kemunculan\n
oleh(?:\n|\r\n?)
.sumber
Jika setiap file hanya memiliki satu urutan asam amino, saya tidak akan menggunakan ekspresi reguler sama sekali. Sesuatu seperti ini:
sumber
Temukan:
\ 1 = some_varying_text
\ 2 = baris dari semua CAPS
Edit (bukti bahwa ini berfungsi):
sumber
Berikut ini adalah ekspresi reguler yang cocok dengan blok teks multiline:
sumber
Preferensi saya.
Pada titik ini Anda memiliki someVaryingText sebagai string, dan asam sebagai daftar string. Anda bisa melakukannya
"".join( acids )
dengan membuat satu senar.Saya merasa ini kurang membuat frustrasi (dan lebih fleksibel) daripada multiline regex.
sumber