Normal ifade etiketler arasındaki tüm metni seç


143

2 etiket arasındaki tüm metni seçmenin en iyi yolu nedir - ör: sayfadaki tüm 'ön' etiketler arasındaki metin.


2
Python iseniz "Güzel Çorba" gibi bir html-ayrıştırıcı kullanmak için en iyi yol ...
Fredrik Pihl

1
En iyi yol XML / HTML ayrıştırıcısını kullanmaktır.
Daniel O'Hara

4
Genel olarak, html'yi ayrıştırmak için düzenli ifadeler kullanmak iyi bir fikir değildir: stackoverflow.com/questions/1732348/…
murgatroid99

Düzenli olarak iç içe yerleştirilmiş etiketler HTML'yi normal yapmadığından, normal ifade içeren etiketler arasında metin ayrıştırmayın. Etiketleri eşleştirmek uygun görünüyor. /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Yanıtlar:


157

Sen kullanabilirsiniz "<pre>(.*?)</pre>"(istediğiniz herhangi bir metni ile ön değiştirme) ve ilk grubu ayıklamak (daha spesifik talimatlar için bir dil belirtin) ama bu çok basit ve geçerli HTML olduğunu basit kavramı varsayar.

Diğer yorumcuların önerdiği gibi, karmaşık bir şey yapıyorsanız bir HTML ayrıştırıcı kullanın.


41
Bu , etiketler arasındaki metni seçmez, etiketleri içerir.
capikaw


2
Çok satırlı etiketler için: <html_tag> (. +) ((\ S) + (. +)) + <\ / Html_tag>
Felipe Augusto

Bu durum hala görünür durumdadır: <pre>Denedikten sonra hala etiketleri görüyorsanız <pre>(.*?)<\/pre>, bunun nedeni (. *?) Yakalama grubu yerine Tam eşleme tarafından yakalananlara bakmanızdır. Sesler cheesy ama hep düşünüyorum çünkü sürece "hırsızlar parantez = çifti" (bir takip eder ?gibi (?:ya (?>da her maç iki yakalar sahip olacaktır: yakalama grubu için tam eşleşme & 1 için 1. Her ek parantez kümesi ek bir yakalama ekler. Çalıştığınız dilde her iki görüntüyü nasıl alacağınızı bilmeniz yeterlidir.
rbsdca

137

Etiket başka bir satırda tamamlanabilir. Bu yüzden \neklenmesi gerekiyor.

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

5
(.|\n)*?Birden çok satırda HTML etiketleriyle uğraşırken ekleme konusunda önemli nokta . Seçilen cevap yalnızca HTML etiketleri aynı satırdaysa çalışır.
Caleuanhopkins

3
Windows satır sonları için <PRE> (. | \ N | \ r \ n) *? <\ / PRE>
Mark

3
Hiçbir (.|\n)*?karakterle eşleştirmek için asla kullanmayın . Her zaman (tek satırlı) değiştirici .ile kullanın s. Veya [\s\S]*?geçici bir çözüm.
Wiktor Stribiżew

Ben notepad ++ kod yorumları seçmek istedim, bu yüzden bu cevap kullanarak /\*(.|\n)*?\*/hangi iş yaptı - teşekkür ederim
wkille

mükemmel cevap çok teşekkürler
Omda

25

Ben bunu kullanardım.

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

Temel olarak yaptığı şey:

(?<=(<pre>))Seçim <pre>etiketle başlamalıdır

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )Bu sadece uygulamak istediğim normal bir ifade. Bu durumda, örnekte köşeli parantez içinde listelenen harf, rakam veya satırsonu karakterini veya bazı özel karakterleri seçer. Boru karakteri |basitçe " VEYA " anlamına gelir .

+?Artı karakter, yukarıdakilerden birini veya daha fazlasını seçmek için durum belirtisi önemli değildir. Soru işareti varsayılan davranışı 'açgözlü' durumdan 'ungreedy' olarak değiştirir.

(?=(</pre>))Seçim </pre>etikete eklenmelidir

resim açıklamasını buraya girin

Kullanım durumunuza bağlı olarak ( i veya m ) gibi bazı değiştiriciler eklemeniz gerekebilir

  • i - büyük / küçük harfe duyarlı değil
  • m - çok satırlı arama

Burada bu aramayı Sublime Text'de gerçekleştirdim, böylece normal ifademde değiştiriciler kullanmak zorunda kalmadım.

Javascript lookbehind'ı desteklemiyor

Yukarıdaki örnek PHP, Perl, Java gibi dillerle iyi çalışmalıdır ... Javascript, lookbehind'i desteklemediğinden (?<=(<pre>)), bir tür geçici çözümü kullanmayı unutmamalıyız . Belki de burada olduğu gibi her seçim için sonuçlarımızdan ilk dört karakteri soyun Regex etiketleri arasındaki eşleşme metni

Ayrıca yakalamayan parantezler için JAVASCRIPT REGEX DOKÜMANTASYONUNA bakın


Normal ifadeyi bir dizeye koymak için `/ ile tek / çift tırnak işareti karakterlerinden kaçmanız gerektiğini unutmayın.
David Zwart

18

öğe arasında içerik almak için aşağıdaki kalıbı kullanın. [tag]İçeriği çıkarmak istediğiniz gerçek öğeyle değiştirin .

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

Bazen etiketler, anchoretiket sahibi gibi özelliklere sahip olur href, ardından aşağıdaki kalıbı kullanır.

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

İlk örneği '<head> (. +?) </head>' olarak deneyin ve beklendiği gibi çalışır. Ama ikincisiyle sonuçum yok.
Alex Byrth

1
bu işe yaramıyor. <[tag]>maç olacak <t>, <a>ve<g>
Martin Schneider

2
@ MA-Maddin - Sanırım Replace [tag] with the actual element you wish to extract the content fromkısmı kaçırdın .
LWC

2
Ah, evet. Bunlar []tamamen atlanmış olmalıydı. Bu, RegEx'teki anlamları ve insanların önce kodu
Martin Schneider

15

Sınırlayıcı etiketleri hariç tutmak için:

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

(?<=<pre>) sonra metin arar <pre>

(?=</pre>) daha önce metin arar </pre>

Sonuçlar preetiketin içindeki metni


Bunu kullanan kişiler, içeriğin etiketler arasında yeni bir çizgiye sahip olup olmadığını da düşünebilen @krishna thakor'un cevabına bakarlar
KingKongCoder

Bu benim durumumda yardımcı oldu (yeni satırları düşünmeye gerek yok). Teşekkürler.
Pking

6

HTML ile regexes ayrıştırmaya çalışmamalısınız bu soruyu görün ve nasıl ortaya çıktığını görün.

En basit terimlerle, html normal bir dil değildir, bu yüzden düzenli ifadelerle tam olarak ayrıştıramazsınız.

Yuvalanmış benzer etiket olmadığında html alt kümelerini ayrıştırabileceğinizi söyledikten sonra. Dolayısıyla, etiketin kendisi arasında ve dışında bir şey olmadığı sürece, bu işe yarayacaktır:

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

Daha iyi bir fikir, html'nizi yüklemek için yerel DOMDocument gibi bir ayrıştırıcı kullanmak, ardından etiketinizi seçmek ve böyle bir şeye benzeyebilecek iç html'yi almaktır:

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

Ve bu uygun bir ayrıştırıcı olduğu için yuvalama etiketlerini vb.


2
Normal ifadenin yanında uygun bir çözüm sağlayan tek cevap bu olsa da, hala hala vekilleri topladığımdan biraz rahatsız olduğumu söylemek istiyorum ve ayrıca muhtemelen doğru yol olmadığına dair geniş bir uyarı ekledim ... En azından cevabımla ilgili neyin yanlış olduğu hakkında yorum yap lütfen.
sg3s

1
Soru ile etiketlenmedi php. PHP'nin resme nasıl geldiğinden emin değilim ...
trincot

@trincot Bu 7 yıldan uzun bir süre önceydi, bu yüzden hatırlayamıyorum. Her durumda, sorunun bir normal ifade ve ayrıştırıcı ile çözülmesine bir örnektir. Regex iyidir ve php o zamanlar iyi biliyordum.
sg3s

Anlıyorum, ilk yorumunuzu gördüm ve bunun bazı aşağı oyları açıklayabileceğini düşündüm.
trincot


4

Bu bulduğum her şeyin en basit düzenli ifadesi gibi görünüyor

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. Açılış etiketini (?:<TAG>)maçlardan hariç tutma
  2. ([\s\S]*)Eşleşmelere boşluk veya boşluk olmayan karakterleri dahil et
  3. Kapatma etiketini (?:<\/TAG>)eşleşmelerden hariç tut

3

Bu cevap etrafa bakmak için destek gerektirir! Bu, açılış ve kapanış etiketi çiftleri arasındaki tüm metni tanımlamamı sağladı. '>' Ve '<' arasındaki tüm metin budur. Etrafında çalışır çünkü etrafına baktığı karakterleri tüketmez.

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

Bu HTML parçasını kullanarak https://regex101.com/ adresinde test ettim .

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

Bu üç bölümden oluşan bir oyun: arkaya bakış, içerik ve ileriye bakış.

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

ekran yakalama from regex101.com

Ben 10 için bir başlangıç ​​olarak hizmet umuyoruz. Şans.


Teşekkür ederim. Sadece bu daha iyi bir cevap değil, aynı zamanda regex101 sitesine harika bir bağlantı. 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); });

Kabul edilen cevap javascript kodu olmadığından, şunu ekleyerek:


1

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)bu normal ifade etiket arasındaki her şeyi seçecektir. yeni çizgide olursa olsun (çok satırlı çalışın.


1

Python'da, DOTALLbayrağın ayarlanması yeni satırlar dahil her şeyi yakalar.

DOTALL bayrağı belirtilmişse, bu yeni satır dahil herhangi bir karakterle eşleşir. 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!

Bir belgedeki tüm açılış ve kapanış etiketleri arasında metin yakalama

Bir belgedeki tüm açılış ve kapanış etiketleri arasında metin yakalamak finditeriçin kullanışlıdır. Aşağıdaki örnekte <pre>, dizede üç açılış ve kapanış etiketi bulunmaktadır.

#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

Birden çok satır için:

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


0

Bu çözümü kullanıyorum:

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

-1

Javascript'te (diğerleri arasında), bu basittir. Nitelikleri ve birden çok satırı kapsar:

/<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
Lütfen cevabınızı kelimeleri kullanarak açıklayınız.
Andrew Regan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.