Regex pilih semua teks di antara tag

143

Apa cara terbaik untuk memilih semua teks antara 2 tag - mis: teks antara semua tag 'pra' pada halaman.

basheps
sumber
2
Cara terbaik adalah dengan menggunakan html-parser seperti "Beautiful Soup" jika Anda menggunakan python ...
Fredrik Pihl
1
Cara terbaik adalah dengan menggunakan parser XML / HTML.
Daniel O'Hara
4
Secara umum, menggunakan ekspresi reguler untuk mem-parsing html bukan ide yang baik: stackoverflow.com/questions/1732348/…
murgatroid99
Jangan parsing teks antara tag dengan regex karena tag bersarang secara sewenang-wenang menjadikan HTML tidak biasa. Tag yang cocok tampaknya baik-baik saja. /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Jawaban:

157

Anda dapat menggunakan "<pre>(.*?)</pre>", (mengganti pra dengan teks apa pun yang Anda inginkan) dan mengekstrak grup pertama (untuk instruksi yang lebih spesifik menentukan bahasa) tetapi ini mengasumsikan gagasan sederhana bahwa Anda memiliki HTML yang sangat sederhana dan valid.

Seperti yang disarankan komentator lain, jika Anda melakukan sesuatu yang kompleks, gunakan parser HTML.

PyKing
sumber
41
Ini tidak memilih teks di antara tag, itu termasuk tag.
capikaw
3
Anda harus mengambil pilihan menggunakan ()
Sahu V Kumar
2
Untuk tag multi-baris: <html_tag> (. +) ((\ S) + (. +)) + <\ / Html_tag>
Felipe Augusto
Ini masih memiliki visibilitas jadi: Jika Anda masih melihat <pre>tag setelah mencoba <pre>(.*?)<\/pre>, itu karena Anda melihat apa yang ditangkap oleh pertandingan Penuh alih-alih kelompok tangkapan (. *?). Kedengarannya murahan tapi saya selalu berpikir "kurung = sepasang pencuri" karena kecuali (diikuti oleh ?seperti dalam (?:atau (?>, setiap pertandingan akan memiliki dua tangkapan: 1 untuk pertandingan penuh & 1 untuk kelompok tangkapan. Setiap set kurung tambahan menambahkan tangkapan tambahan. Anda hanya harus tahu cara mengambil kedua tangkapan dalam bahasa apa pun yang Anda gunakan.
rbsdca
137

Tag dapat diselesaikan di baris lain. Inilah sebabnya mengapa \nperlu ditambahkan.

<PRE>(.|\n)*?<\/PRE>
zac
sumber
5
Poin penting tentang menambahkan (.|\n)*?ketika berurusan dengan tag HTML di beberapa baris. Jawaban yang dipilih hanya berfungsi jika tag HTML berada di baris yang sama.
Caleuanhopkins
3
<PRE> (. | \ N | \ r \ n) *? <\ / PRE> untuk akhiran jalur Windows
Tandai
3
Jangan pernah gunakan (.|\n)*?untuk mencocokkan arang. Selalu gunakan .dengan spengubah (singleline). Atau [\s\S]*?solusinya.
Wiktor Stribiżew
Saya ingin memilih komentar kode di notepad ++, jadi dengan menggunakan jawaban ini saya datang dengan /\*(.|\n)*?\*/yang melakukan pekerjaan - terima kasih
wkille
jawaban sempurna terima kasih banyak
Omda
25

Inilah yang akan saya gunakan.

(?<=(<pre>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|`~]| )+?(?=(</pre>))

Pada dasarnya yang dilakukannya adalah:

(?<=(<pre>))Pilihan harus diawali dengan <pre>tag

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )Ini hanya ungkapan reguler yang ingin saya terapkan. Dalam hal ini, ia memilih huruf atau digit atau karakter baris baru atau beberapa karakter khusus yang tercantum dalam contoh dalam tanda kurung. Karakter pipa |hanya berarti " ATAU ".

+?Status karakter Plus untuk memilih satu atau lebih di atas - urutan tidak masalah. Tanda tanya mengubah perilaku default dari 'serakah' menjadi 'ungreedy'.

(?=(</pre>))Seleksi harus ditambahkan oleh </pre>tag

masukkan deskripsi gambar di sini

Tergantung pada kasus penggunaan Anda, Anda mungkin perlu menambahkan beberapa pengubah seperti ( i atau m )

  • i - case-insensitive
  • m - pencarian multi-line

Di sini saya melakukan pencarian ini di Sublime Text jadi saya tidak perlu menggunakan pengubah di regex saya.

Javascript tidak mendukung tampilan di belakang

Contoh di atas seharusnya bekerja dengan baik dengan bahasa seperti PHP, Perl, Java ... Javascript, bagaimanapun, tidak mendukung tampilan di belakang sehingga kita harus melupakan tentang menggunakan (?<=(<pre>))dan mencari beberapa jenis solusi. Mungkin lepaskan empat karakter pertama dari hasil kami untuk setiap pilihan seperti di sini Regex mencocokkan teks di antara tag

Lihat juga JAVASCRIPT REGEX DOCUMENTATION untuk tanda kurung yang tidak diambil

DevWL
sumber
Perhatikan bahwa Anda harus keluar dari karakter kutipan tunggal / ganda dengan `untuk menempatkan regexp dalam sebuah string.
David Zwart
18

gunakan pola di bawah ini untuk mendapatkan konten di antara elemen. Ganti [tag]dengan elemen aktual yang ingin Anda ekstrak kontennya.

<[tag]>(.+?)</[tag]>

Kadang tag akan memiliki atribut, seperti anchortag yang dimiliki href, lalu gunakan pola di bawah ini.

 <[tag][^>]*>(.+?)</[tag]>
Shravan Ramamurthy
sumber
Coba contoh pertama sebagai '<head> (. +?) </head>' dan berfungsi seperti yang diharapkan. Tetapi saya tidak memiliki hasil dengan yang kedua.
Alex Byrth
1
ini tidak berhasil. <[tag]>akan cocok <t>, <a>dan<g>
Martin Schneider
2
@ MA-Maddin - Saya pikir Anda melewatkan Replace [tag] with the actual element you wish to extract the content frombagian itu.
LWC
2
Oh, ya. Ini []seharusnya dihilangkan sama sekali. Itu akan lebih jelas, karena maknanya dalam RegEx dan fakta, bahwa orang memindai kode terlebih dahulu dan membaca teks setelah;)
Martin Schneider
14

Untuk mengecualikan tag pembatas:

(?<=<pre>)(.*?)(?=</pre>)

(?<=<pre>) mencari teks setelahnya <pre>

(?=</pre>) mencari teks sebelumnya </pre>

Hasil akan teks di dalam pretag

Jean-Simon Collard
sumber
Orang-orang menggunakan tampilan ini pada jawaban @krishna thakor yang juga dapat mempertimbangkan apakah konten memiliki baris baru di antara tag
KingKongCoder
Ini membantu dalam kasus saya (tidak perlu mempertimbangkan baris baru). Terima kasih.
Pking
6

Anda seharusnya tidak mencoba menguraikan html dengan regex melihat pertanyaan ini dan bagaimana hasilnya.

Dalam istilah yang paling sederhana, html bukan bahasa biasa sehingga Anda tidak dapat sepenuhnya menguraikannya dengan ekspresi reguler.

Setelah mengatakan bahwa Anda dapat mengurai himpunan bagian html ketika tidak ada tag yang sama bersarang. Jadi, selama ada apa pun di antara dan bukan tag itu sendiri, ini akan berfungsi:

preg_match("/<([\w]+)[^>]*>(.*?)<\/\1>/", $subject, $matches);
$matches = array ( [0] => full matched string [1] => tag name [2] => tag content )

Ide yang lebih baik adalah menggunakan parser, seperti DOMDocument asli, untuk memuat html Anda, lalu pilih tag Anda dan dapatkan html dalam yang mungkin terlihat seperti ini:

$obj = new DOMDocument();
$obj -> load($html);
$obj -> getElementByTagName('el');
$value = $obj -> nodeValue();

Dan karena ini adalah parser yang tepat, ia akan dapat menangani tag bersarang dll.

sg3s
sumber
2
Hanya ingin mengatakan saya sedikit terganggu bahwa ini masih mengumpulkan downvotes sementara itu adalah satu-satunya jawaban yang memasok solusi yang tepat di sebelah regex dan saya juga menambahkan banyak peringatan bahwa itu mungkin bukan cara yang benar ... Setidaknya mengomentari apa yang salah tentang jawaban saya.
sg3
1
Pertanyaan tidak ditandai php. Tidak yakin bagaimana PHP muncul dalam gambar ...
trincot
@trincot Ini lebih dari 7 tahun yang lalu, jadi saya tidak ingat. Bagaimanapun, ini adalah contoh pemecahan masalah dengan regex dan parser. Regexnya bagus dan php adalah apa yang saya ketahui dengan baik pada saat itu.
sg3
Saya mengerti, saya melihat komentar pertama Anda dan berpikir bahwa ini bisa menjelaskan beberapa downvotes.
trincot
4

Coba ini....

(?<=\<any_tag\>)(\s*.*\s*)(?=\<\/any_tag\>)
Heriberto Rivera
sumber
3
Perhatikan bahwa tampilan belakang tidak didukung dalam JavaScript.
allicarn
Ooo tentu saja, tetapi regex ini untuk Jawa. terima kasih atas catatan anda.
Heriberto Rivera
4

Ini sepertinya ungkapan reguler paling sederhana dari semua yang saya temukan

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. Kecualikan tag pembuka (?:<TAG>)dari pertandingan
  2. Sertakan karakter spasi putih atau non-spasi putih ([\s\S]*)dalam pertandingan
  3. Kecualikan tag penutup (?:<\/TAG>)dari pertandingan
maqduni
sumber
3

Jawaban ini mengandaikan dukungan untuk melihat-lihat! Ini memungkinkan saya untuk mengidentifikasi semua teks antara pasang tag pembuka dan penutup. Itu semua teks antara '>' dan '<'. Ini bekerja karena melihat-lihat tidak mengkonsumsi karakter yang cocok.

(? <=>) ([\ w \ s] +) (? = </)

Saya mengujinya di https://regex101.com/ menggunakan fragmen HTML ini.

<table>
<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>
<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>
</table>

Ini adalah permainan tiga bagian: tampilan belakang, konten, dan tampilan depan.

(?<=>)    # look behind (but don't consume/capture) for a '>'
([\w\s]+) # capture/consume any combination of alpha/numeric/whitespace
(?=<\/)   # look ahead  (but don't consume/capture) for a '</'

tangkapan layar dari regex101.com

Saya berharap itu berfungsi sebagai awal untuk 10. Keberuntungan.

Clarius
sumber
Terima kasih. Tidak hanya ini jawaban yang lebih baik, tetapi juga tautan yang bagus ke situs regex101. Terpilih! 🙂
Sean Feldman
2

var str = "Lorem ipsum <pre>text 1</pre> Lorem ipsum <pre>text 2</pre>";
    str.replace(/<pre>(.*?)<\/pre>/g, function(match, g1) { console.log(g1); });

Karena jawaban yang diterima tanpa kode javascript, maka tambahkan bahwa:

Shishir Arora
sumber
1

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)regex ini akan memilih semua tag antara. tidak masalah apakah itu di baris baru (bekerja dengan multiline.

Krishna thakor
sumber
1

Dalam Python, pengaturan DOTALLbendera akan menangkap semuanya, termasuk baris baru.

Jika bendera DOTALL telah ditentukan, ini cocok dengan karakter apa pun termasuk baris baru. docs.python.org

#example.py using Python 3.7.4  
import re

str="""Everything is awesome! <pre>Hello,
World!
    </pre>
"""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set 
pattern = re.compile(r"<pre>(.*)</pre>",re.DOTALL)
matches = pattern.search(str)

print(matches.group(1))

python example.py

Hello,
World!

Menangkap teks antara semua tag pembuka dan penutup dalam dokumen

Untuk menangkap teks antara semua tag pembuka dan penutup dalam dokumen, finditerberguna. Dalam contoh di bawah ini, tiga <pre>tag pembuka dan penutup hadir dalam string.

#example2.py using Python 3.7.4
import re

# str contains three <pre>...</pre> tags
str = """In two different ex-
periments, the authors had subjects chat and solve the <pre>Desert Survival Problem</pre> with a
humorous or non-humorous computer. In both experiments the computer made pre-
programmed comments, but in study 1 subjects were led to believe they were interact-
ing with another person. In the <pre>humor conditions</pre> subjects received a number of funny
comments, for instance: “The mirror is probably too small to be used as a signaling
device to alert rescue teams to your location. Rank it lower. (On the other hand, it
offers <pre>endless opportunity for self-reflection</pre>)”."""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set
# The question mark in (.*?) indicates non greedy matching.
pattern = re.compile(r"<pre>(.*?)</pre>",re.DOTALL)

matches = pattern.finditer(str)


for i,match in enumerate(matches):
    print(f"tag {i}: ",match.group(1))

python example2.py

tag 0:  Desert Survival Problem
tag 1:  humor conditions
tag 2:  endless opportunity for self-reflection
John
sumber
0

Untuk beberapa baris:

<htmltag>(.+)((\s)+(.+))+</htmltag>
Dilip
sumber
0

Kamu bisa memakai Pattern pattern = Pattern.compile( "[^<'tagname'/>]" );

Ambrish Rajput
sumber
0

Saya menggunakan solusi ini:

preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
var_dump($new);
T.Todua
sumber
-1

Dalam Javascript (antara lain), ini sederhana. Ini mencakup atribut dan beberapa baris:

/<pre[^>]*>([\s\S]*?)<\/pre>/
Jonathan
sumber
-4
<pre>([\r\n\s]*(?!<\w+.*[\/]*>).*[\r\n\s]*|\s*[\r\n\s]*)<code\s+(?:class="(\w+|\w+\s*.+)")>(((?!<\/code>)[\s\S])*)<\/code>[\r\n\s]*((?!<\w+.*[\/]*>).*|\s*)[\r\n\s]*<\/pre>
pengguna5988518
sumber
6
Harap perkenalkan / jelaskan jawaban Anda menggunakan kata-kata.
Andrew Regan