Regex เลือกข้อความทั้งหมดระหว่างแท็ก


143

เป็นวิธีที่ดีที่สุดในการเลือกข้อความทั้งหมดระหว่าง 2 แท็ก - เช่น: ข้อความระหว่างแท็ก 'pre' ทั้งหมดในหน้า


2
วิธีที่ดีที่สุดคือการใช้ HTML-parser เช่น "สวยซุป" ถ้าคุณเป็นงูหลาม ...
Fredrik พิห์ล

1
วิธีที่ดีที่สุดคือใช้ตัวแยกวิเคราะห์ XML / HTML
Daniel O'Hara

4
โดยทั่วไปแล้วการใช้นิพจน์ทั่วไปเพื่อแยกวิเคราะห์ HTML ไม่ใช่ความคิดที่ดี: stackoverflow.com/questions/1732348/…
murgatroid99

อย่าแยกข้อความระหว่างแท็กด้วย regex เพราะแท็กที่ซ้อนกันโดยพลการทำให้ HTML ไม่ปกติ ดูเหมือนว่าการจับคู่แท็กจะไม่เป็นไร /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

คำตอบ:


157

คุณสามารถใช้"<pre>(.*?)</pre>"(แทนที่ข้อความที่คุณต้องการก่อน) และแยกกลุ่มแรก (สำหรับคำแนะนำที่เฉพาะเจาะจงมากขึ้นระบุภาษา) แต่สิ่งนี้ถือว่าความคิดง่าย ๆ ว่าคุณมี HTML ที่เรียบง่ายและถูกต้องมาก

ตามที่ผู้แสดงความคิดเห็นคนอื่นแนะนำไว้หากคุณกำลังทำอะไรที่ซับซ้อนให้ใช้โปรแกรมแยกวิเคราะห์ HTML


41
นี่ไม่ได้เลือกข้อความระหว่างแท็ก แต่จะรวมถึงแท็กด้วย
capikaw

3
คุณต้องคว้าตัวเลือกโดยใช้ ()
Sahu V Kumar

2
สำหรับแท็กหลายบรรทัด: <html_tag> (. +) ((s s) + (. +)) + <\ / html_tag>
เฟลิเป้ออกัสโต

สิ่งนี้ยังคงมีการเปิดเผยดังนี้: หากคุณยังคงเห็น<pre>แท็กหลังจากลอง<pre>(.*?)<\/pre>แล้วอาจเป็นเพราะคุณกำลังดูสิ่งที่จับคู่แบบเต็มแทนกลุ่มจับภาพ (. *?) ฟังดูวิเศษ แต่ฉันมักจะคิดว่า "วงเล็บ = คู่ของขโมย" เพราะถ้า(ตามมาด้วย?ใน(?:หรือ(?>ทุกการแข่งขันจะมีการจับสอง: 1 สำหรับการแข่งขันเต็ม & 1 สำหรับกลุ่มการจับ วงเล็บเพิ่มเติมแต่ละชุดจะเพิ่มการดักจับเพิ่มเติม คุณเพียงแค่ต้องรู้วิธีดึงข้อมูลการจับทั้งสองในภาษาที่คุณใช้ด้วย
rbsdca

137

แท็กสามารถเสร็จสมบูรณ์ในอีกบรรทัดหนึ่ง นี่คือเหตุผล\nที่ต้องเพิ่ม

<PRE>(.|\n)*?<\/PRE>

5
จุดสำคัญเกี่ยวกับการเพิ่ม(.|\n)*?เมื่อจัดการกับแท็ก HTML ข้ามหลายบรรทัด คำตอบที่เลือกใช้งานได้ก็ต่อเมื่อแท็ก HTML อยู่ในบรรทัดเดียวกัน
Caleuanhopkins

3
<PRE> (. | \ n | \ r \ n) *? <\ / PRE> สำหรับการสิ้นสุดบรรทัด Windows
ทำเครื่องหมาย

3
อย่าใช้(.|\n)*?เพื่อจับคู่อักขระใด ๆ ใช้.กับsตัวปรับ (singleline) เสมอ หรือ[\s\S]*?วิธีแก้ปัญหา
Wiktor Stribiżew

ฉันต้องการที่จะเลือกรหัสความคิดเห็นใน notepad ++ ดังนั้นการใช้คำตอบนี้ฉัน/\*(.|\n)*?\*/จึงได้งานที่ - ขอบคุณ
wkille

คำตอบที่สมบูรณ์แบบขอบคุณมาก
Omda

25

นี่คือสิ่งที่ฉันจะใช้

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

โดยพื้นฐานแล้วมันคืออะไร:

(?<=(<pre>))การเลือกจะต้องเสริมด้วย<pre>แท็ก

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )นี่เป็นเพียงนิพจน์ปกติที่ฉันต้องการใช้ ในกรณีนี้มันจะเลือกตัวอักษรหรือตัวเลขหรือตัวอักษรขึ้นบรรทัดใหม่หรือตัวอักษรพิเศษบางอย่างที่ระบุไว้ในตัวอย่างในวงเล็บเหลี่ยม อักขระ|ไพพ์หมายถึง " หรือ "

+?เครื่องหมายบวกระบุสถานะเพื่อเลือกคำสั่งด้านบนอย่างน้อยหนึ่งคำสั่งไม่สำคัญ เครื่องหมายคำถามเปลี่ยนพฤติกรรมเริ่มต้นจาก 'โลภ' เป็น 'ไม่จัดการ'

(?=(</pre>))การเลือกจะต้องต่อท้ายด้วย</pre>แท็ก

ป้อนคำอธิบายรูปภาพที่นี่

ขึ้นอยู่กับกรณีการใช้งานของคุณคุณอาจต้องเพิ่มตัวดัดแปลงบางอย่างเช่น ( iหรือm )

  • i - ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
  • m - การค้นหาหลายบรรทัด

ที่นี่ฉันทำการค้นหานี้ใน Sublime Text ดังนั้นฉันไม่ต้องใช้ตัวดัดแปลงใน regex ของฉัน

Javascript ไม่สนับสนุน lookbehind

ตัวอย่างด้านบนควรทำงานได้ดีกับภาษาเช่น PHP, Perl, Java ... Javascript แต่ไม่สนับสนุน lookbehind ดังนั้นเราต้องลืมเกี่ยวกับการใช้งาน(?<=(<pre>))และค้นหาวิธีแก้ปัญหาบางอย่าง อาจจะง่าย ๆ ตัดตัวอักษรสี่ตัวแรกออกจากผลลัพธ์ของเราสำหรับการเลือกแต่ละรายการเช่นที่นี่ Regex จับคู่ข้อความระหว่างแท็ก

ดูที่JAVASCRIPT REGEX DOCUMENTATIONสำหรับวงเล็บที่ไม่ได้ถ่าย


โปรดทราบว่าคุณต้องหลีกเลี่ยงอักขระเครื่องหมายคำพูดเดี่ยว / คู่ด้วย `เพื่อใส่ regexp ในสตริง
David Zwart

18

ใช้รูปแบบด้านล่างเพื่อรับเนื้อหาระหว่างองค์ประกอบ แทนที่[tag]ด้วยองค์ประกอบจริงที่คุณต้องการดึงเนื้อหาออกมา

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

บางครั้งแท็กจะมีแอตทริบิวต์เช่นใช้anchorแท็กhrefแล้วใช้รูปแบบด้านล่าง

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

ลองตัวอย่างแรกเป็น '<head> (. +?) </head>' และทำงานอย่างที่คาดไว้ แต่ฉันไม่มีผลกับอันที่สอง
Alex Byrth

1
มันไม่ทำงาน <[tag]>จะตรงกับ<t>, <a>และ<g>
มาร์ตินชไนเดอ

2
@ MA-Maddin - ฉันคิดว่าคุณพลาดReplace [tag] with the actual element you wish to extract the content fromส่วนนี้ไป
LWC

2
ใช่แล้ว สิ่งเหล่านี้[]ควรถูกตัดออกไปโดยสิ้นเชิง ที่จะมีความชัดเจนมากขึ้นเพราะความหมายของพวกเขาใน RegEx และความจริงที่ว่าคนสแกนรหัสแรกและอ่านข้อความหลังจาก;)
มาร์ตินชไนเดอ

14

หากต้องการยกเว้นแท็กที่คั่นให้ทำดังนี้

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

(?<=<pre>) ค้นหาข้อความ <pre>

(?=</pre>) ค้นหาข้อความก่อน </pre>

ผลลัพธ์จะมีข้อความอยู่ภายในpreแท็ก


ผู้ใช้ที่ดูคำตอบของ @krishna thakor ซึ่งสามารถพิจารณาได้ว่าเนื้อหามีบรรทัดใหม่ระหว่างแท็กหรือไม่
KingKongCoder

สิ่งนี้ช่วยในกรณีของฉัน (ไม่จำเป็นต้องพิจารณาบรรทัดใหม่) ขอบคุณ
Pking

6

คุณไม่ควรพยายามแยก html ด้วย regexes ดูคำถามนี้และวิธีการเปิด

ในคำศัพท์ที่ง่ายที่สุด html ไม่ใช่ภาษาปกติดังนั้นคุณจึงไม่สามารถแยกวิเคราะห์ได้ทั้งหมดคือใช้นิพจน์ทั่วไป

ต้องบอกว่าคุณสามารถแยกชุดย่อยของ html เมื่อไม่มีแท็กที่ซ้อนกันคล้ายกัน ดังนั้นตราบใดที่สิ่งใดระหว่างและไม่ใช่แท็กนั้นสิ่งนี้จะทำงาน:

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

ความคิดที่ดีกว่าคือใช้ parser เช่น DOMDocument ดั้งเดิมเพื่อโหลด html ของคุณจากนั้นเลือกแท็กของคุณและรับ html ภายในซึ่งอาจมีลักษณะดังนี้:

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

และเนื่องจากเป็นตัวแยกวิเคราะห์ที่เหมาะสมจึงจะสามารถจัดการแท็กการทำรังเป็นต้น


2
แค่อยากจะบอกว่าฉันค่อนข้างรำคาญว่านี่ยังคงรวบรวม downvotes ในขณะที่มันเป็นคำตอบเดียวที่ให้ทางออกที่เหมาะสมถัดจาก regex และฉันยังเพิ่มคำเตือนมากมายว่ามันอาจไม่ใช่วิธีที่ถูกต้อง ... อย่างน้อยก็แสดงความคิดเห็นในสิ่งที่ผิดเกี่ยวกับคำตอบของฉันได้โปรด
sg3s

1
phpคำถามที่ไม่ได้ติดแท็กด้วย ไม่แน่ใจว่า PHP มาในภาพ ...
trincot

@trincot นี่เป็นมากกว่า 7 ปีที่แล้วดังนั้นฉันจำไม่ได้ ในกรณีใด ๆ มันเป็นตัวอย่างของการแก้ปัญหาด้วย regex และ parser regex นั้นดีและ php เป็นสิ่งที่ฉันรู้ดีในเวลานั้น
sg3s

ฉันเข้าใจฉันเห็นความคิดเห็นแรกของคุณและคิดว่านี่สามารถอธิบาย downvotes บางส่วนได้
trincot

5

ลองสิ่งนี้ ....

(?<=\<any_tag\>)(\s*.*\s*)(?=\<\/any_tag\>)

3
โปรดทราบว่า JavaScript ไม่ได้รับการสนับสนุน
allicarn

Ooo แน่นอน แต่ regex นี้สำหรับ Java ขอบคุณสำหรับบันทึกของคุณ
Heriberto Rivera

4

นี่น่าจะเป็นการแสดงออกที่ธรรมดาที่สุดของสิ่งที่ฉันพบ

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. ยกเว้นแท็กเปิด(?:<TAG>)จากการแข่งขัน
  2. รวมอักขระช่องว่างหรืออักขระที่ไม่ใช่ช่องว่าง([\s\S]*)ในการแข่งขัน
  3. ยกเว้นแท็กปิด(?:<\/TAG>)จากรายการที่ตรงกัน

3

คำตอบนี้ไม่สนับสนุนการมองไปรอบ ๆ ! สิ่งนี้ทำให้ฉันสามารถระบุข้อความทั้งหมดระหว่างคู่ของแท็กเปิดและปิด นั่นคือข้อความทั้งหมดระหว่าง '>' และ '<' มันใช้งานได้เพราะการมองไปรอบ ๆ ไม่ใช้ตัวละครที่ตรงกัน

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

ฉันทดสอบในhttps://regex101.com/โดยใช้ส่วน HTML นี้

<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>

มันเป็นเกมสามส่วน: การมองไปข้างหลังเนื้อหาและการมองไปข้างหน้า

(?<=>)    # 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 '</'

การดักจับหน้าจอจาก regex101.com

ฉันหวังว่าจะทำหน้าที่เป็นการเริ่มต้นสำหรับ 10. โชค


ขอบคุณ. ไม่เพียงแค่นี้เป็นคำตอบที่ดีกว่า แต่ยังเป็นลิงค์ที่ยอดเยี่ยมไปยังไซต์ regex101 upvoted! 🙂
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); });

เนื่องจากคำตอบที่ยอมรับคือไม่มีรหัสจาวาสคริปต์ดังนั้นให้เพิ่ม:


1

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)regex นี้จะเลือกทุกอย่างระหว่างแท็ก ไม่ว่าจะอยู่ในบรรทัดใหม่ (ทำงานกับ multiline


1

ใน Python การตั้งค่าDOTALLสถานะจะจับทุกอย่างรวมถึงการขึ้นบรรทัดใหม่

หากระบุค่าสถานะ DOTALL สิ่งนี้จะจับคู่อักขระใด ๆ รวมถึงการขึ้นบรรทัดใหม่ 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!

การจับข้อความระหว่างแท็กเปิดและแท็กปิดทั้งหมดในเอกสาร

ในการจับภาพข้อความระหว่างแท็กเปิดและแท็กปิดทั้งหมดในเอกสารfinditerจะมีประโยชน์ ในตัวอย่างด้านล่าง<pre>แท็กเปิดและปิดสามแท็กมีอยู่ในสตริง

#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




-1

ใน Javascript (รวมถึงอื่น ๆ ) นี่เป็นเรื่องง่าย ครอบคลุมคุณลักษณะและหลายบรรทัด:

/<pre[^>]*>([\s\S]*?)<\/pre>/

-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>

6
กรุณาแนะนำ / อธิบายคำตอบของคุณด้วยคำพูด
Andrew Regan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.