Regex chọn tất cả văn bản giữa các thẻ


143

Cách tốt nhất để chọn tất cả văn bản giữa 2 thẻ - ví dụ: văn bản giữa tất cả các thẻ 'pre' trên trang.


2
Cách tốt nhất là sử dụng trình phân tích cú pháp html như "Beautiful Soup" nếu bạn thích trăn ...
Fredrik Pihl

1
Cách tốt nhất là sử dụng trình phân tích cú pháp XML / HTML.
Daniel O'Hara

4
Nói chung, sử dụng các biểu thức thông thường để phân tích html không phải là một ý tưởng hay: stackoverflow.com/questions/1732348/ Lời
murgatroid99

Không phân tích văn bản giữa các thẻ với regex vì các thẻ được lồng tùy ý làm cho HTML không đều. Phù hợp với thẻ có vẻ là ổn. /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Câu trả lời:


157

Bạn có thể sử dụng "<pre>(.*?)</pre>", (thay thế trước bằng bất kỳ văn bản nào bạn muốn) và trích xuất nhóm đầu tiên (để có hướng dẫn cụ thể hơn xác định ngôn ngữ) nhưng điều này giả định khái niệm đơn giản rằng bạn có HTML rất đơn giản và hợp lệ.

Như các nhà bình luận khác đã đề xuất, nếu bạn đang làm gì đó phức tạp, hãy sử dụng trình phân tích cú pháp HTML.


41
Điều này không chọn văn bản giữa các thẻ, nó bao gồm các thẻ.
capikaw

3
Bạn cần lấy lựa chọn bằng cách sử dụng ()
Sahu V Kumar

2
Đối với thẻ nhiều dòng: <html_tag> (. +) ((\ S) + (. +)) + <\ / Html_tag>
Felipe Augusto

Điều này vẫn có khả năng hiển thị vì vậy: Nếu bạn vẫn thấy <pre>các thẻ sau khi thử <pre>(.*?)<\/pre>, thì đó là vì bạn đang xem những gì được chụp bởi Full khớp thay vì nhóm chụp (. *?). Nghe có vẻ nhảm nhưng tôi luôn nghĩ "ngoặc đơn = cặp kẻ trộm" bởi vì trừ khi (được theo sau bởi hoặc ?trong , mọi trận đấu sẽ có hai lần bắt: 1 cho toàn bộ trận đấu & 1 cho nhóm bắt giữ. Mỗi bộ dấu ngoặc đơn bổ sung thêm một bản chụp bổ sung. Bạn chỉ cần biết cách truy xuất cả hai ảnh chụp bằng bất kỳ ngôn ngữ nào bạn đang làm việc. (?:(?>
rbsdca

137

Tag có thể được hoàn thành trong một dòng khác. Đây là lý do tại sao \ncần phải được thêm vào.

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

5
Điểm quan trọng về việc thêm (.|\n)*?khi xử lý các thẻ HTML trên nhiều dòng. Câu trả lời được chọn chỉ hoạt động nếu các thẻ HTML nằm trên cùng một dòng.
Caleuanhopkins

3
<PRE> (. | \ N | \ r \ n) *? <\ / PRE> cho các kết thúc dòng Windows
Đánh dấu

3
Không bao giờ sử dụng (.|\n)*?để phù hợp với bất kỳ char. Luôn luôn sử dụng .với ssửa đổi (singleline). Hoặc một [\s\S]*?cách giải quyết.
Wiktor Stribiżew

Tôi muốn chọn nhận xét mã trong notepad ++, vì vậy bằng cách sử dụng câu trả lời này, tôi đã /\*(.|\n)*?\*/nghĩ ra công việc nào - cảm ơn bạn
wkille

câu trả lời hoàn hảo cảm ơn rất nhiều
Omda

25

Đây là những gì tôi sẽ sử dụng.

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

Về cơ bản những gì nó làm là:

(?<=(<pre>))Lựa chọn phải được thêm vào bằng <pre>thẻ

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )Đây chỉ là một biểu thức thông thường tôi muốn áp dụng. Trong trường hợp này, nó chọn ký tự hoặc chữ số hoặc ký tự dòng mới hoặc một số ký tự đặc biệt được liệt kê trong ví dụ trong ngoặc vuông. Ký tự ống |chỉ đơn giản là " HOẶC ".

+?Thêm trạng thái ký tự để chọn một hoặc nhiều thứ ở trên - thứ tự không quan trọng. Dấu hỏi thay đổi hành vi mặc định từ 'tham lam' thành 'không tham lam'.

(?=(</pre>))Lựa chọn phải được thêm vào bởi </pre>thẻ

nhập mô tả hình ảnh ở đây

Tùy thuộc vào trường hợp sử dụng của bạn, bạn có thể cần thêm một số sửa đổi như ( i hoặc m )

  • i - trường hợp không nhạy cảm
  • m - tìm kiếm nhiều dòng

Ở đây tôi đã thực hiện tìm kiếm này trong Sublime Text để tôi không phải sử dụng công cụ sửa đổi trong regex của mình.

Javascript không hỗ trợ giao diện

Ví dụ trên sẽ hoạt động tốt với các ngôn ngữ như PHP, Perl, Java ... Javascript, tuy nhiên, không hỗ trợ giao diện nên chúng ta phải quên sử dụng (?<=(<pre>))và tìm kiếm một cách giải quyết khác. Có lẽ đơn giản tước bốn ký tự đầu tiên từ kết quả của chúng tôi cho mỗi lựa chọn như ở đây Regex khớp văn bản giữa các thẻ

Ngoài ra, hãy nhìn vào TÀI LIỆU ĐĂNG KÝ JAVASCRIPT cho các dấu ngoặc đơn không bắt giữ


Lưu ý rằng bạn cần thoát các ký tự trích dẫn đơn / kép bằng `để đặt biểu thức chính quy trong chuỗi.
David Zwart

18

sử dụng mẫu dưới đây để có được nội dung giữa các yếu tố. Thay thế [tag]bằng các yếu tố thực tế bạn muốn trích xuất nội dung từ.

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

Đôi khi các thẻ sẽ có các thuộc tính, như anchorthẻ có href, sau đó sử dụng mẫu bên dưới.

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

Hãy thử ví dụ đầu tiên là '<head> (. +?) </ Head>' và hoạt động như mong đợi. Nhưng tôi không có kết quả với cái thứ hai.
Alex Byrth

1
cái này không hoạt động. <[tag]>sẽ phù hợp <t>, <a><g>
Martin Schneider

2
@ MA-Maddin - Tôi nghĩ bạn đã bỏ lỡ Replace [tag] with the actual element you wish to extract the content fromphần này.
LWC

2
Ồ tốt, vâng. Chúng []nên được bỏ qua hoàn toàn. Điều đó sẽ rõ ràng hơn, bởi vì ý nghĩa của chúng trong RegEx và thực tế là mọi người quét mã trước và đọc văn bản sau;)
Martin Schneider

14

Để loại trừ các thẻ phân định:

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

(?<=<pre>) tìm văn bản sau <pre>

(?=</pre>) tìm văn bản trước </pre>

Kết quả sẽ nhắn tin bên trong prethẻ


Những người sử dụng cái nhìn này vào câu trả lời của @krishna thakor cũng có thể xem xét liệu nội dung có dòng mới giữa các thẻ hay không
KingKongCoder

Điều này đã giúp trong trường hợp của tôi (không cần phải xem xét các dòng mới). Cảm ơn.
Pking

6

Bạn không nên cố phân tích html bằng regexes để xem câu hỏi này và cách nó được bật ra.

Nói một cách đơn giản nhất, html không phải là ngôn ngữ thông thường, do đó bạn không thể phân tích cú pháp hoàn toàn bằng các biểu thức thông thường.

Phải nói rằng bạn có thể phân tích các tập hợp con của html khi không có các thẻ tương tự được lồng vào nhau. Vì vậy, miễn là bất cứ thứ gì giữa và không phải là thẻ đó, nó sẽ hoạt động:

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

Một ý tưởng tốt hơn là sử dụng một trình phân tích cú pháp, như DOMDocument, để tải html của bạn, sau đó chọn thẻ của bạn và lấy html bên trong có thể trông giống như thế này:

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

Và vì đây là một trình phân tích cú pháp thích hợp, nó sẽ có thể xử lý các thẻ lồng nhau, v.v.


2
Chỉ muốn nói rằng tôi hơi băn khoăn rằng điều này vẫn đang thu thập downvote trong khi đó là câu trả lời duy nhất cung cấp giải pháp phù hợp bên cạnh regex và tôi cũng đã thêm cảnh báo rộng rãi rằng có lẽ đó không phải là cách đúng đắn ... Ít nhất là nhận xét về những gì sai về câu trả lời của tôi, xin vui lòng.
sg3s

1
Câu hỏi không được gắn thẻ php. Không chắc chắn làm thế nào PHP đi vào hình ảnh ...
trincot

@trincot Điều này đã hơn 7 năm trước, vì vậy tôi không thể nhớ. Trong mọi trường hợp, đây là một ví dụ về giải quyết vấn đề bằng biểu thức chính quy và trình phân tích cú pháp. Regex là tốt và php chỉ là những gì tôi biết rõ vào thời điểm đó.
sg3s

Tôi hiểu, tôi đã thấy bình luận đầu tiên của bạn và nghĩ rằng điều này có thể giải thích một số downvote.
trincot

4

Thử cái này....

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

3
Lưu ý rằng nhìn phía sau không được hỗ trợ trong JavaScript.
allicarn

Tất nhiên, nhưng regex này là dành cho Java. cảm ơn bạn đã lưu ý
Heriberto Rivera

4

Đây dường như là biểu thức chính quy đơn giản nhất trong tất cả những gì tôi tìm thấy

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. Không bao gồm thẻ mở (?:<TAG>) từ các trận đấu
  2. Bao gồm bất kỳ ký tự khoảng trắng hoặc không khoảng trắng ([\s\S]*) trong các kết quả khớp
  3. Loại trừ thẻ đóng (?:<\/TAG>)khỏi các trận đấu

3

Câu trả lời này giả sử hỗ trợ cho cái nhìn xung quanh! Điều này cho phép tôi xác định tất cả văn bản giữa các cặp thẻ mở và đóng. Đó là tất cả văn bản giữa '>' và '<'. Nó hoạt động vì nhìn xung quanh không tiêu thụ các ký tự mà nó khớp.

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

Tôi đã thử nghiệm nó trong https://regex101.com/ bằng cách sử dụng đoạn HTML này.

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

Đây là một trò chơi gồm ba phần: cái nhìn phía sau, nội dung và cái nhìn phía trước.

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

chụp màn hình từ regex101.com

Tôi hy vọng rằng phục vụ như là một khởi đầu cho 10. May mắn.


Cảm ơn bạn. Đây không chỉ là một câu trả lời tốt hơn, mà còn là một liên kết tuyệt vời đến trang web regex101. Nâng cao! 🙂
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); });

Vì câu trả lời được chấp nhận là không có mã javascript, vì vậy, thêm rằng:


1

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)regex này sẽ chọn mọi thứ giữa các thẻ. không có vấn đề gì trong dòng mới (làm việc với multiline.


1

Trong Python, thiết lập DOTALLcờ sẽ nắm bắt mọi thứ, bao gồm cả dòng mới.

Nếu cờ DOTALL đã được chỉ định, điều này khớp với bất kỳ ký tự nào kể cả dòng mới. 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!

Chụp văn bản giữa tất cả các thẻ mở và đóng trong tài liệu

Để chụp văn bản giữa tất cả các thẻ mở và đóng trong tài liệu, finditerrất hữu ích. Trong ví dụ dưới đây, ba <pre>thẻ mở và đóng có mặt trong chuỗi.

#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

0

Đối với nhiều dòng:

<htmltag>(.+)((\s)+(.+))+</htmltag>


0

Tôi sử dụng giải pháp này:

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

-1

Trong Javascript (trong số những người khác), điều này là đơn giản. Nó bao gồm các thuộc tính và nhiều dòng:

/<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
Hãy giới thiệu / giải thích câu trả lời của bạn bằng cách sử dụng từ ngữ.
Andrew Regan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.