RegEx, XHTML स्व-निहित टैग को छोड़कर खुले टैग से मेल खाता है


1473

मुझे इन सभी शुरुआती टैग से मिलान करना होगा:

<p>
<a href="foo">

लेकिन ये नहीं:

<br />
<hr class="foo" />

मैं इसके साथ आया था और यह सुनिश्चित करना चाहता था कि मैंने इसे सही कर लिया है। मैं केवल कब्जा कर रहा हूं a-z

<([a-z]+) *[^/]*?>

मेरा मानना ​​है कि यह कहता है:

  • कम-से-कम खोजें, फिर
  • खोजें (और कैप्चर करें) एक या अधिक बार, तब
  • शून्य या अधिक रिक्त स्थान खोजें, फिर
  • कोई भी वर्ण शून्य या अधिक बार, लालची को छोड़कर /, तब खोजें
  • अधिक से अधिक खोजें

क्या मेरे पास वह अधिकार है? और इससे भी महत्वपूर्ण बात, आपको क्या लगता है?

जवाबों:


4417

आप regex के साथ [X] HTML को पार्स नहीं कर सकते। क्योंकि HTML को regex द्वारा पार्स नहीं किया जा सकता है। Regex एक ऐसा उपकरण नहीं है जिसका उपयोग HTML को सही ढंग से पार्स करने के लिए किया जा सकता है। जैसा कि मैंने पहले भी यहाँ कई बार HTML-and-regex सवालों के जवाब दिए हैं, regex का उपयोग आपको HTML का उपभोग करने की अनुमति नहीं देगा। नियमित अभिव्यक्ति एक उपकरण है जो HTML द्वारा नियोजित निर्माणों को समझने के लिए अपर्याप्त रूप से परिष्कृत है। HTML एक नियमित भाषा नहीं है और इसलिए इसे नियमित रूप से अभिव्यक्त नहीं किया जा सकता है। Regex क्वेरीज़ HTML को उसके सार्थक भागों में तोड़ने के लिए सुसज्जित नहीं हैं। इतनी बार लेकिन यह मुझे नहीं मिल रहा है। यहां तक ​​कि पेरेल द्वारा उपयोग किए गए अनियमित नियमित अभिव्यक्तियाँ HTML को पार्स करने के कार्य तक नहीं हैं। आप मुझे कभी क्रैक नहीं करेंगे। HTML पर्याप्त जटिलता की एक भाषा है जिसे इसे नियमित अभिव्यक्तियों द्वारा पार्स नहीं किया जा सकता है। यहां तक ​​कि जॉन स्कीट नियमित अभिव्यक्ति का उपयोग करके HTML को पार्स नहीं कर सकता है। हर बार जब आप नियमित भावों के साथ HTML को पार्स करने का प्रयास करते हैं, तो अपवित्र बच्चा कुंवारी लड़कियों का खून रोता है, और रूसी हैकर्स आपके वेबप को pwn करते हैं। Regex के साथ HTML को पार्स करना आत्माओं को जीवित के दायरे में बुलाता है। HTML और regex एक साथ चलते हैं जैसे कि प्रेम, विवाह और अनुष्ठान शिशु। <केंद्र> इसे रोक नहीं सकता है बहुत देर हो चुकी है। रेगेक्स और HTML का बल एक ही वैचारिक अंतरिक्ष में एक साथ आपके दिमाग को नष्ट कर देगा, जैसे कि बहुत अधिक पानी। यदि आप HTML को regex के साथ पार्स करते हैं, तो आप उन्हें दे रहे हैं और उनके ईश निंदा के तरीके, जो हम सभी के लिए अमानवीय शौचालय हैं, जिसका नाम बेसिक बहुभाषी विमान में व्यक्त नहीं किया जा सकता है, वह आता है। HTML-plus-regexp आपके द्वारा अवलोकन किए जाने के दौरान, आपके मानस को आतंक के हमले में झकझोरने वाले भाव के n izes को रोक देगा।यह बहुत देर हो चुकी है बहुत देर हो चुकी है हमें बचाया नहीं जा सकता क्योंकि चीगल्ड सुनिश्चित करता है कि रेगेक्स सभी जीवित ऊतक का उपभोग करेगा (HTML को छोड़कर, जो कि यह नहीं हो सकता है, जैसा कि पहले से भविष्यवाणी नहीं की गई थी) प्रिय प्रभु हमारी मदद करें कि कैसे कोई भी रेगीज से पार्स का उपयोग करके इस संकट से बच सकता है एचटीएमएल भय यातना और सुरक्षा संबंधी दोषों की एक अनंत काल के लिए मानवता बर्बाद किया है रेगे का उपयोग कर प्रक्रिया एचटीएमएल करने के लिए एक उपकरण के रूप में एक्स एक Brea स्थापित करता है इस दुनिया के बीच ch और भ्रष्ट संस्थाओं के भय दायरे (SGML संस्थाओं की तरह है, लेकिन अधिक भ्रष्ट) एक मात्र glimp से की reg की दुनिया HTML के लिए पूर्व पारसर्स होगा इन्स tantly परिवहन एपी rogrammer की चेतना मैं nto aw orl निरंतर चिल्ला के घ, वह आता है, विनाशक sl ithy regex संक्रमण Wil l अपने एचटी खा एमएल पार्सर, आवेदन और विजुअल बेसिक की तरह सभी समय के लिए अस्तित्व केवल बदतर वह आता है वह कॉम तों ऐसा नहीं फाई GHT ज ई आता है, हाय रों अपवित्र चमक डी stro҉ying सभी ज्ञान, HTML टैग लीक fr̶ǫm यो उर आँखों की तरह liq uid पी ऐन, नियमित रूप से exp फिर से गीत ssion पार्स exti जाएगा मोर की आवाज nguish एसपी से ताल आदमी यहाँ मैं देख सकता हूँ यह आप देख सकते हैं यह यह सुंदर टी है वह च inal snuffing ओ च झूठ मैन सभी खो ए के एस एल एल मैं SLOST वें ई वह आ टट्टू रों वह कॉम तों वह सह मुझे रों टी वह Ich या permeat तों अल एल मेरी एफ ए सी ई मेरा चेहरा ᵒh देवता एन ओ नहीं Noo हे पर Θ रोक टी वह एक * ̶͑̾̾ जीएल ES ͎a̧͈͖r̽̾̈́͒͑en OT r raΌl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGͮ̂҉̯͈͕̹̘̱ IS͇̹̺ͅƝ̴ȳ̳ T O̘ THË͖́̉ ͠ ̯͍̭P̯͍̭O̡ N̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘Y̶̧̨̱̹̭̯ͧ̾ͬ H̐ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝


क्या आपने इसके बजाय XML पार्सर का उपयोग करने की कोशिश की है?


मॉडरेटर का नोट

यह पोस्ट अपनी सामग्री के लिए अनुपयुक्त संपादन को रोकने के लिए लॉक की गई है। यह पोस्ट बिल्कुल वैसा ही दिखता है जैसा कि यह देखने के लिए है - इसकी सामग्री के साथ कोई समस्या नहीं है। कृपया इसे हमारे ध्यान में न रखें।


179
कोबी: मुझे लगता है कि रेग्क्स ऑफिसर के साथ असिस्टेंट डोन्ट पार्से एचटीएमएल का पद छोड़ने का समय नहीं है। कोई बात नहीं हम इसे कितनी बार कहते हैं, वे हर दिन आना बंद नहीं करेंगे ... हर घंटे भी। यह एक खोया हुआ कारण है, जिसे कोई और व्यक्ति थोड़ा-बहुत लड़ सकता है। तो, अगर आप अवश्य ही regex के साथ HTML को पार्स करें। यह केवल टूटा हुआ कोड है, जीवन और मृत्यु नहीं।
बॉब

27
क्या इस उत्तर को पार्स करने के लिए RegEx का उपयोग करना संभव है?
क्रिस पोर्टर

2
यदि आप इस पोस्ट को नहीं देख सकते हैं, तो इसकी महिमा में इसकी एक व्याख्या है
एंड्रयू केटॉन

3247

जबकि मनमाना HTML के साथ केवल एक regex असंभव है, यह कभी कभी एक पार्स करने के लिए उन्हें इस्तेमाल करने के उपयुक्त है सीमित है, जाना जाता है HTML के सेट।

यदि आपके पास HTML पृष्ठों का एक छोटा सा सेट है जिसे आप डेटा से अलग करना चाहते हैं और फिर डेटाबेस में सामान बनाते हैं, तो रेग्जेस ठीक काम कर सकता है। उदाहरण के लिए, मैं हाल ही में ऑस्ट्रेलियाई संघीय प्रतिनिधियों के नाम, पार्टियों और जिलों को प्राप्त करना चाहता था, जो मुझे संसद की वेब साइट से मिला। यह एक सीमित, एक बार का काम था।

रेगेक्स ने मेरे लिए बस ठीक काम किया, और सेट करने के लिए बहुत तेज़ थे।


131
इसके अलावा, बड़े दस्तावेज़ों से नियमित रूप से प्रारूपित डेटा को स्क्रैप करना किसी भी सामान्य पार्सर की तुलना में स्कैन और रेगेक्स के विवेकपूर्ण उपयोग के साथ तेजी से होने वाला है। और अगर आप कोडिंग रेगेक्स के साथ सहज हैं, तो कोडिंग xpaths की तुलना में तेजी से कोड करें। और जो आप स्क्रैप कर रहे हैं उसमें बदलाव के लिए लगभग निश्चित रूप से कम नाजुक है। तो ब्लाह।
माइकल जॉनसन

255
@MichaelJohnston "कम नाजुक"? लगभग निश्चित रूप से नहीं। एक्सएमएल पार्सर की तुलना में टेक्स्ट-फ़ॉर्मेटिंग विवरणों के बारे में रेग्क्स की देखभाल चुपचाप अनदेखा कर सकती है। &foo;एन्कोडिंग और CDATAअनुभागों के बीच स्विच करना ? अपने दस्तावेज़ में सभी व्हाट्सएप को हटाने के लिए एक HTML मिनीफ़ायर का उपयोग करना जो ब्राउज़र रेंडर नहीं करता है? एक XML पार्सर परवाह नहीं करेगा, और न ही एक अच्छी तरह से लिखा XPath बयान होगा। एक रेगेक्स-आधारित "पार्सर", दूसरी ओर ...
चार्ल्स डफी

41
@CharlesDuffy एक बार की नौकरी के लिए ठीक है, और रिक्त स्थान के लिए हम \ 's +
क्वांटम

68
@xiaomao वास्तव में, अगर 80% समाधान प्राप्त करने के लिए सभी गोचरों और वर्कअराउंड को जानना है जो बाकी समय "आपके लिए काम करता है" विफल रहता है, तो मैं आपको रोक नहीं सकता। इस बीच, मैं बाड़ के मेरी तरफ पारसर्स का उपयोग कर रहा हूं जो सिंटैक्टिक रूप से मान्य XML के 100% पर काम करते हैं।
चार्ल्स डफी

374
मुझे एक बार ~ 10k पृष्ठों पर कुछ डेटा खींचना पड़ा, सभी एक ही HTML टेम्पलेट के साथ। वे एचटीएमएल त्रुटियों से अटे पड़े थे, जिसके कारण पार्स चोक हो जाते थे, और उनकी सारी स्टाइल इनलाइन या <font>आदि के साथ होती थी । DOM को नेविगेट करने में मदद करने के लिए कोई क्लास या आईडी नहीं। "सही" दृष्टिकोण के साथ पूरे दिन लड़ने के बाद, मैं आखिरकार एक रेगेक्स समाधान में बदल गया और एक घंटे में काम कर रहा था।
पॉल ए जंगविर्थ

2037

मुझे लगता है कि दोष यह है कि HTML एक चॉम्स्की टाइप 2 व्याकरण (संदर्भ मुक्त व्याकरण) है और RegEx एक चॉम्स्की टाइप 3 व्याकरण (नियमित व्याकरण) है । चूँकि टाइप 3 व्याकरण की तुलना में टाइप 2 व्याकरण मौलिक रूप से अधिक जटिल है ( चॉम्स्की पदानुक्रम देखें ), XML को RegEx के साथ पार्स करना गणितीय रूप से असंभव है।

लेकिन कई लोग कोशिश करेंगे, कुछ भी सफलता का दावा करेंगे - लेकिन जब तक दूसरों को गलती नहीं मिलेगी और आप पूरी तरह से गड़बड़ करेंगे।


225
ओपी XHTML: टैग्स के एक बहुत ही सीमित उप-भाग को पार्स करने के लिए कह रहा है। क्या करता है (एक्स) एचटीएमएल एक सीएफजी अन्य तत्वों के प्रारंभ और अंत टैग (एक व्याकरण नियम के अनुसार A -> s A e) के बीच तत्व रखने की अपनी क्षमता है । (X) HTML में यह संपत्ति एक स्टार्ट टैग के भीतर नहीं है : एक प्रारंभ टैग में अन्य प्रारंभ टैग नहीं हो सकते। जिस उपसमुदाय को ओपी पार्स करने की कोशिश कर रहा है वह सीएफजी नहीं है।
लार्स

101
सीएस सिद्धांत रूप में, सुव्यवस्थित भाषाओँ हैं विषय से मुक्त भाषाओं के एक सख्त सबसेट है, लेकिन मुख्य धारा प्रोग्रामिंग भाषाओं में नियमित अभिव्यक्ति कार्यान्वयन अधिक शक्तिशाली हैं। जैसा कि noulakaz.net/weblog/2007/03/18/… वर्णन करता है, तथाकथित "नियमित अभिव्यक्तियाँ" अभाज्य संख्याओं में अभाज्य संख्याओं की जाँच कर सकती हैं, जो निश्चित रूप से कुछ है जो CS सिद्धांत से एक नियमित अभिव्यक्ति प्राप्त नहीं कर सकती है।
एडम मिहलसिन

11
@eyelidlessness: वही "केवल यदि" सभी CFG पर लागू होता है, तो क्या यह नहीं है? यानी अगर (X) HTML इनपुट अच्छी तरह से नहीं बना है, तो एक पूर्ण विकसित XML पार्सर भी मज़बूती से काम नहीं करेगा। हो सकता है कि यदि आप "(एक्स) एचटीएमएल सिंटैक्स त्रुटियों को वास्तविक दुनिया उपयोगकर्ता एजेंटों में लागू किया गया हो" का उदाहरण देते हैं, तो आप समझ जाएंगे कि आपको बेहतर क्या मिल रहा है।
12:09

82
@ अदममहलसीन बिल्कुल सही है। अधिकांश एक्स्टेंट रेगेक्स इंजन चॉम्स्की टाइप 3 व्याकरण (जैसे गैर-लालची मिलान, बैकरेफ़्स) की तुलना में अधिक शक्तिशाली हैं। कुछ रेगेक्स इंजन (जैसे पर्ल के) ट्यूरिंग पूर्ण हैं। यह सच है कि HTML को पार्स करने के लिए भी वे खराब उपकरण हैं, लेकिन यह अक्सर उद्धृत तर्क का कारण नहीं है।
डब्यूजिम

26
यह यहां सबसे "पूर्ण और संक्षिप्त" उत्तर है। यह लोगों को औपचारिक व्याकरण और भाषाओं की मूल बातें सीखने की उम्मीद करता है और उम्मीद है कि कुछ गणित भी होगा, ताकि वे बहुपत्नी समय में एनपी-कार्यों को हल करने जैसी आशाहीन चीजों पर समय बर्बाद न करें
mishmashru

1332

इन लोगों को मत सुनो। यदि आप कार्य को छोटे टुकड़ों में तोड़ते हैं, तो आप रेगेक्स के साथ संदर्भ-मुक्त व्याकरण को पूरी तरह से पार्स कर सकते हैं। आप एक स्क्रिप्ट के साथ सही पैटर्न उत्पन्न कर सकते हैं जो इनमें से प्रत्येक को क्रम में करता है:

  1. हल करने की समस्या का समाधान करें।
  2. एक वर्ग को स्क्वायर करें।
  3. O (लॉग एन) या उससे कम में ट्रैवलिंग सेल्समैन समस्या का समाधान करें। यदि यह इससे अधिक है, तो आप रैम से बाहर निकलेंगे और इंजन हैंग हो जाएगा।
  4. पैटर्न बहुत बड़ा होगा, इसलिए सुनिश्चित करें कि आपके पास एक एल्गोरिथ्म है जो दोषरहित यादृच्छिक डेटा को संकुचित करता है।
  5. लगभग वहाँ - बस पूरी बात को शून्य से विभाजित करें। बहुत आसान।

मैंने पिछले भाग को स्वयं पूरा नहीं किया है, लेकिन मुझे पता है कि मैं पास हो रहा हूं। यह CthulhuRlyehWgahnaglFhtagnExceptionकिसी कारण से एस फेंक रहा है, इसलिए मैं इसे वीबी 6 में पोर्ट करने जा रहा हूं और उपयोग कर रहा हूं On Error Resume Next। मैं इस अजीब दरवाजे की जांच करने के बाद एक बार कोड के साथ अपडेट करूंगा जो कि दीवार में खोला गया था। हम्म।

पीएस पियरे डे फ़र्मेट ने यह भी पता लगाया कि यह कैसे करना है, लेकिन वह जो मार्जिन लिख रहा था वह कोड के लिए पर्याप्त नहीं था।


80
आपके द्वारा उल्लेखित की तुलना में शून्य से तलाक एक बहुत आसान समस्या है। यदि आप सादे फ़्लोटिंग पॉइंट अंकगणित (जो सभी को होना चाहिए लेकिन कोई भी नहीं है) के बजाय अंतराल का उपयोग करते हैं, तो आप ख़ुशी से [कुछ अंतराल युक्त] शून्य से कुछ विभाजित कर सकते हैं। परिणाम केवल एक अंतराल है जिसमें प्लस और माइनस इन्फिनिटी है।
rjmunro

147
आधुनिक टेक्स्ट-एडिटिंग सॉफ़्टवेयर में नरम मार्जिन द्वारा Fermat की छोटी मार्जिन समस्या हल हो गई है।
kd4ttc

50
रैंडल मुनरो द्वारा
फेटर्स

29
जानकारी के लिए: फर्मा समस्या है वास्तव में 1995 में हल किया गया , और यह केवल गणितज्ञों 358 साल ऐसा करने के लिए ले लिया।
jmiserez

10
मैं कोल्ड फ्यूजन से प्राप्त ब्राउनियन रैटचेट्स का उपयोग करके उस चिपचिपा विभाजन-दर-शून्य कदम को बायपास करने में सक्षम था ... हालांकि यह केवल तभी काम करता है जब मैं कॉस्मोलॉजिकल स्थिरांक को हटा देता हूं।
टिम लेहनर

1072

अस्वीकरण : यदि आपके पास विकल्प है तो एक पार्सर का उपयोग करें। ने कहा कि...

यह HTML टैग्स से मिलान करने के लिए मेरे द्वारा इस्तेमाल किया गया regex है:

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>

यह सही नहीं हो सकता है, लेकिन मैंने बहुत सारे HTML के माध्यम से इस कोड को चलाया । ध्यान दें कि यह भी अजीब चीजों को पकड़ता है <a name="badgenerator"">, जो वेब पर दिखाई देते हैं।

मुझे लगता है कि यह स्व-निहित टैग से मेल नहीं खाता, आप या तो कोबी के नकारात्मक लुक-पीछे का उपयोग करना चाहते हैं :

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+(?<!/\s*)>

या बस गठबंधन और अगर नहीं।

डाउनवोटर्स के लिए: यह वास्तविक उत्पाद से कोड काम कर रहा है। मुझे संदेह है कि इस पृष्ठ को पढ़ने वाले किसी को भी यह आभास हो जाएगा कि यह HTML पर रीजिक्स का उपयोग करने के लिए सामाजिक रूप से स्वीकार्य है।

कैविएट : मुझे ध्यान देना चाहिए कि यह रेगेक्स अभी भी सीडीएटीए ब्लॉक, टिप्पणियों, और स्क्रिप्ट और शैली तत्वों की उपस्थिति में टूट जाता है। अच्छी खबर है, आप एक regex का उपयोग कर उन लोगों से छुटकारा पा सकते हैं ...


94
मैं कुछ ऐसी चीज़ों के साथ जाऊंगा जो सार्वभौमिक रूप से सही नहीं होने के बारे में रोने की तुलना में समझदार चीजों पर काम करती है :-)
प्रजेश कुमार

55
क्या कोई HTML के अंदर CDATA का उपयोग कर रहा है?
डेन्यूबियन नाविक

16
इसलिए आप वास्तव में केवल regexp के साथ पार्सिंग समस्या को हल नहीं करते हैं, लेकिन पार्सर के एक हिस्से के रूप में यह काम कर सकता है। पुनश्च: काम करने वाले उत्पाद का मतलब अच्छे कोड से नहीं है। कोई अपराध नहीं है, लेकिन यह है कि औद्योगिक प्रोग्रामिंग कैसे काम करती है और उनके पैसे मिलते हैं
मिशमश्रु

32
आपका रेगेक्स बहुत ही कम संभव वैध HTML पर विफल होने लगता है: <!doctype html><title><</title> :। जबकि साधारण '<!doctype html><title><</title>'.match(/<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>/g)रिटर्न ["<!doctype html>", "<title>", "<</title>"]चाहिए ["<title>", "</title>"]

2
यदि हम दिए गए उदाहरणों का मिलान करने और न करने की कोशिश कर रहे हैं, तो /<.( "foo"> <br /> <घंटा वर्ग = "foo" />'.match(/<.([^r>][^>]*)?>/g)
imma

506

ऐसे लोग हैं जो आपको बताएंगे कि पृथ्वी गोल है (या शायद यह कि पृथ्वी एक गोलाकार गोलाकार है यदि वे अजीब तरह का उपयोग करना चाहते हैं)। वे झूठ बोल रहे हैं।

ऐसे लोग हैं जो आपको बताएंगे कि रेगुलर एक्सप्रेशंस को पुनरावर्ती नहीं होना चाहिए। वे आपको सीमित कर रहे हैं। उन्हें आपको अपने वश में करने की आवश्यकता है, और वे आपको अज्ञान में रखकर करते हैं।

आप उनकी वास्तविकता में रह सकते हैं या लाल गोली ले सकते हैं।

लॉर्ड मार्शल की तरह (क्या वह मार्शल। नेट क्लास का रिश्तेदार है?), मैंने अंडरवॉटर स्टैक बेस्ड रेगेक्स- वर्ड देखा है और शक्तियों के ज्ञान के साथ लौटाया है जिसकी आप कल्पना नहीं कर सकते हैं। हां, मुझे लगता है कि एक पुराने एक या दो उनकी रक्षा कर रहे थे, लेकिन वे टीवी पर फुटबॉल देख रहे थे, इसलिए यह मुश्किल नहीं था।

मुझे लगता है कि XML केस काफी सरल है। RegEx (.NET सिंटैक्स में), अपने कमजोर दिमाग द्वारा समझने में आसान बनाने के लिए बेस 64 में अपस्फीति और कोडित, कुछ इस तरह होना चाहिए:

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
+r/vD34mUADO1P4/AQAA//8=

सेट करने के लिए विकल्प है RegexOptions.ExplicitCapture। जिस कैप्चर ग्रुप की आपको तलाश है, वह है ELEMENTNAME। यदि कब्जा समूह ERRORखाली नहीं है, तो एक पार्सिंग त्रुटि थी और रेगेक्स बंद हो गया।

यदि आपको मानव-पठनीय रेगेक्स में पुन: संयोजन करने में समस्या है, तो यह मदद करनी चाहिए:

static string FromBase64(string str)
{
    byte[] byteArray = Convert.FromBase64String(str);

    using (var msIn = new MemoryStream(byteArray))
    using (var msOut = new MemoryStream()) {
        using (var ds = new DeflateStream(msIn, CompressionMode.Decompress)) {
            ds.CopyTo(msOut);
        }

        return Encoding.UTF8.GetString(msOut.ToArray());
    }
}

यदि आप अनिश्चित हैं, नहीं, मैं मजाक नहीं कर रहा हूं (लेकिन शायद मैं झूठ बोल रहा हूं)। यह काम करेगा। मैंने इसे जांचने के लिए कई टन यूनिट टेस्ट बनाए हैं, और मैंने कंफर्मेशन टेस्ट का इस्तेमाल भी किया है । यह एक टोकन है, एक पूर्ण विकसित पार्सर नहीं है, इसलिए यह केवल XML को अपने घटक टोकन में विभाजित करेगा। यह DTDs को पार्स / एकीकृत नहीं करेगा।

ओह ... यदि आप कुछ सहायक विधियों के साथ रेगेक्स का स्रोत कोड चाहते हैं:

एक xml या पूर्ण सादे regex togeize regex


68
अच्छा भगवान, यह बड़े पैमाने पर है। मेरा सबसे बड़ा सवाल यह है कि क्यों? आपको लगता है कि सभी आधुनिक भाषाओं में XML पार्सर है, है ना? आप 3 लाइनों की तरह यह सब कर सकते हैं और सुनिश्चित करें कि यह काम करेगा। इसके अलावा, क्या आप यह भी महसूस करते हैं कि शुद्ध रेगेक्स निश्चित रूप से कुछ चीजें करने में असमर्थ है? जब तक आपने हाइब्रिड रेगेक्स / इंपॉर्टेंट कोड पार्सर नहीं बनाया है, लेकिन यह आपके जैसा नहीं दिखता है। क्या आप यादृच्छिक डेटा को भी संपीड़ित कर सकते हैं?
जस्टिन मॉर्गन

112
@ जस्टिन मुझे एक कारण की आवश्यकता नहीं है। यह किया जा सकता है (और यह अवैध / अनैतिक नहीं था), इसलिए मैंने इसे किया है। मन को कोई सीमा नहीं है, सिवाय इसके कि हम स्वीकार करते हैं (नेपोलियन हिल) ... आधुनिक भाषाएं XML को पार्स कर सकती हैं? वास्तव में? और मुझे लगा कि यह गैरकानूनी था! :-)
xanatos

76
महोदय, मैं आश्वस्त हूं। मैं इस कोड का उपयोग मेरी स्थायी-गति मशीन के लिए कर्नेल के भाग के रूप में करने जा रहा हूं - क्या आप विश्वास कर सकते हैं कि पेटेंट कार्यालय में मूर्ख मेरे आवेदन को अस्वीकार करते रहेंगे? अच्छा, मैं उन्हें दिखाता हूँ। मैं उन्हें सब दिखा दूंगा!
जस्टिन मॉर्गन

31
@ जस्टिन तो एक्सएमएल पार्सर परिभाषा बग मुक्त है, जबकि रेक्सक्स नहीं है? क्योंकि अगर एक Xml Parser परिभाषा के हिसाब से बग मुक्त नहीं है तो एक xml हो सकता है जो इसे दुर्घटनाग्रस्त कर देता है और हम वापस स्टेप 0 पर आ जाते हैं। चलिए यह बताते हैं: दोनों Xml Parser और यह Regex सभी "कानूनी" को पार्स करने में सक्षम होने का प्रयास करते हैं। “एक्सएमएल। वे कुछ "अवैध" XML को पार्स कर सकते हैं। कीड़े दोनों को दुर्घटनाग्रस्त कर सकते थे। C # XmlReader निश्चित रूप से इस रेगेक्स से अधिक परीक्षण किया गया है।
xanatos

31
नहीं, कुछ भी बग मुक्त नहीं है: 1) सभी कार्यक्रमों में कम से कम एक बग होता है। 2) सभी कार्यक्रमों में अनावश्यक स्रोत कोड की कम से कम एक पंक्ति होती है। 3) # 1 और # 2 द्वारा और तार्किक प्रेरण का उपयोग करके, यह साबित करना एक सरल बात है कि बग के साथ किसी भी कार्यक्रम को कोड की एक पंक्ति में कम किया जा सकता है। (लर्निंग पर्ल से)
स्कॉट वीवर

299

शेल में, आप sed का उपयोग करके HTML को पार्स कर सकते हैं :

  1. Turing.sed
  2. HTML पार्सर (होमवर्क) लिखें
  3. ???
  4. फायदा!

संबंधित (आप regex मैच का उपयोग क्यों नहीं करना चाहिए):


3
मुझे डर है कि तुम्हें मजाक नहीं मिला, @kenorb। कृपया, प्रश्न और स्वीकृत उत्तर को एक बार फिर से पढ़ें। यह सामान्य रूप से HTML पार्सिंग टूल के बारे में नहीं है, और न ही HTML पार्सिंग शेल टूल्स के बारे में, यह रीजेक्स के जरिए HTML को पार्स करने के बारे में है।
पालक

1
नहीं, @ अब्दुल। यह पूरी तरह से, गणितीय रूप से (गणितीय अर्थ में) असंभव है।
पलक

3
हां, यह उत्तर इसे अच्छी तरह से बताता है, @ अब्दुल। ध्यान दें, हालांकि, regex कार्यान्वयन वास्तव में गणितीय अर्थों में नियमित अभिव्यक्ति नहीं हैं - उनके पास ऐसे निर्माण हैं जो उन्हें मजबूत बनाते हैं, अक्सर ट्यूरिंग-पूर्ण (टाइप 0 व्याकरण के बराबर)। इस तथ्य के साथ तर्क टूट जाता है, लेकिन इस अर्थ में अभी भी कुछ हद तक वैध है कि रेगेक्स कभी भी ऐसा काम करने में सक्षम नहीं थे, हालांकि।
पलक

2
और वैसे, मैंने जो मज़ाक का हवाला दिया, वह इस उत्तर की सामग्री केनोर्ब (कट्टरपंथी) संपादन से पहले थी, विशेष रूप से संशोधन 4, @ अब्दुल।
पालेक

3
मजेदार बात यह है कि ओपी ने कभी भी रेगेक्स का उपयोग करके html को पार्स करने के लिए नहीं कहा। उन्होंने regex का उपयोग करके पाठ (जो HTML होता है) से मेल खाने को कहा। जो पूरी तरह से उचित है।
Paralife

274

मैं सहमत हूं कि XML और विशेष रूप से HTML को पार्स करने के लिए सही उपकरण एक नियमित पार्सर है और नियमित अभिव्यक्ति इंजन नहीं है। हालाँकि, जैसे अन्य लोगों ने बताया है, कभी-कभी एक रेग्जिक्स का उपयोग करना तेज, आसान होता है, और यदि आप डेटा प्रारूप जानते हैं तो काम पूरा हो जाता है।

Microsoft वास्तव में .NET फ्रेमवर्क में रेगुलर एक्सप्रेशंस के लिए बेस्ट प्रैक्टिस का एक सेक्शन है और विशेष रूप से इनपुट स्रोत पर विचार [आईएनजी] के बारे में बात करता है

नियमित एक्सप्रेशन की सीमाएँ हैं, लेकिन क्या आपने निम्नलिखित पर विचार किया है?

.NET फ्रेमवर्क अद्वितीय है जब यह नियमित अभिव्यक्तियों की बात करता है कि यह बैलेंसिंग ग्रुप परिभाषाओं का समर्थन करता है ।

इस कारण से, मेरा मानना ​​है कि आप एक्सएमएल को रेग्युलर एक्सप्रेशंस का उपयोग करके पार्स कर सकते हैं। हालाँकि, ध्यान दें कि यह वैध XML होना चाहिए ( ब्राउज़र HTML के बहुत माफ करने वाले हैं और HTML के अंदर खराब XML सिंटैक्स की अनुमति देते हैं )। यह संभव है क्योंकि "बैलेंसिंग ग्रुप डेफिनिशन" नियमित अभिव्यक्ति इंजन को पीडीए के रूप में कार्य करने की अनुमति देगा।

ऊपर उद्धृत 1 लेख से उद्धरण:

.NET नियमित अभिव्यक्ति इंजन

जैसा कि ऊपर वर्णित ठीक से संतुलित निर्माण एक नियमित अभिव्यक्ति द्वारा वर्णित नहीं किया जा सकता है। हालाँकि, .NET नियमित अभिव्यक्ति इंजन कुछ निर्माण प्रदान करता है जो संतुलित निर्माण को मान्यता देता है।

  • (?<group>) - नाम समूह के साथ कैप्चर स्टैक पर कैप्चर किए गए परिणाम को धक्का देता है।
  • (?<-group>) - कैप्चर स्टैक से नाम समूह के साथ शीर्ष सबसे अधिक कैप्चर करता है।
  • (?(group)yes|no) - यदि हाँ नाम समूह के साथ एक समूह मौजूद है तो हाँ भाग से मेल खाता है अन्यथा भाग से मेल नहीं खाता है।

ये निर्माण आवश्यक रूप से स्टैक संचालन के सरल संस्करणों की अनुमति देकर एक प्रतिबंधित पीडीए का अनुकरण करने के लिए .NET नियमित अभिव्यक्ति की अनुमति देते हैं: पुश, पॉप और खाली। साधारण ऑपरेशन वेतन वृद्धि, वेतन वृद्धि के बराबर हैं और क्रमशः शून्य की तुलना करते हैं। यह .NET रेगुलर एक्सप्रेशन इंजन को संदर्भ-मुक्त भाषाओं के सबसेट को पहचानने की अनुमति देता है, विशेष रूप से उन लोगों के लिए जिन्हें केवल एक साधारण काउंटर की आवश्यकता होती है। यह बदले में गैर-पारंपरिक .NET नियमित अभिव्यक्तियों को व्यक्तिगत रूप से संतुलित निर्माणों को पहचानने की अनुमति देता है।

निम्नलिखित नियमित अभिव्यक्ति पर विचार करें:

(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
   <!-- .*? -->                  |
   <[^>]*/>                      |
   (?<opentag><(?!/)[^>]*[^/]>)  |
   (?<-opentag></[^>]*[^/]>)     |
   [^<>]*
)*
(?(opentag)(?!))

झंडे का प्रयोग करें:

  • इकलौती रेखा
  • IgnorePatternWhitespace (आवश्यक नहीं है अगर आप regex को ढहते हैं और सभी व्हाट्सएप को हटा दें)
  • इग्नोरकेस (आवश्यक नहीं)

नियमित अभिव्यक्ति की व्याख्या (इनलाइन)

(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?>                                        # atomic group / don't backtrack (faster)
   <!-- .*? -->                 |          # match xml / html comment
   <[^>]*/>                     |          # self closing tag
   (?<opentag><(?!/)[^>]*[^/]>) |          # push opening xml tag
   (?<-opentag></[^>]*[^/]>)    |          # pop closing xml tag
   [^<>]*                                  # something between tags
)*                                         # match as many xml tags as possible
(?(opentag)(?!))                           # ensure no 'opentag' groups are on stack

आप इसे एक बेहतर .NET नियमित अभिव्यक्ति परीक्षक में आज़मा सकते हैं ।

मैंने इसका नमूना स्रोत इस्तेमाल किया:

<html>
<body>
<div>
   <br />
   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>
</div>
</body>
</html>

यह मैच मिला:

   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>

हालांकि यह वास्तव में इस तरह से निकला:

<ul id="matchMe" type="square">           <li>stuff...</li>           <li>more stuff</li>           <li>               <div>                    <span>still more</span>                    <ul>                         <li>Another &gt;ul&lt;, oh my!</li>                         <li>...</li>                    </ul>               </div>           </li>        </ul>

अंत में, मुझे वास्तव में जेफ एटवुड का लेख पसंद आया: पार्सिंग एचटीएमएल द केथुलु वे । काफी मजेदार है, यह इस सवाल का जवाब बताता है कि वर्तमान में 4k से अधिक वोट हैं।


18
System.TextC # का हिस्सा नहीं है। यह .NET का हिस्सा है।
जॉन सॉन्डर्स 19

8
अपने रेगेक्स की पहली पंक्ति में ( (?=<ul\s*id="matchMe"\s*type="square"\s*>) # match start with <ul id="matchMe"...), "<ul" और "id" के बीच में होना चाहिए , तब तक \s+नहीं \s*, जब तक कि आप इसे <ulid = ...;) से मिलान नहीं करना चाहते
C0deH4cker

@ C0deH4cker आप सही हैं, \s+इसके बजाय अभिव्यक्ति होनी चाहिए \s*
सैम

4
ऐसा नहीं है कि मैं वास्तव में इसे समझता हूं, लेकिन मुझे लगता है कि आपका रेगेक्स विफल रहता है<img src="images/pic.jpg" />
शीथोडोड

3
@Scheintod टिप्पणी के लिए धन्यवाद। मैंने कोड अपडेट किया। पिछली अभिव्यक्ति स्व समापन टैग के /लिए विफल रही जो कहीं न कहीं अंदर थी जो आपके <img src="images/pic.jpg" />HTML के लिए विफल रही ।
सैम

258

मेरा सुझाव है कि PHP में XML और HTML को पार्स करने के लिए QueryPath का उपयोग करें । यह मूल रूप से jQuery के रूप में एक ही वाक्यविन्यास है, केवल यह सर्वर की तरफ है।


8
@ काइल- jQuery XML को पार्स नहीं करता है, यह क्लाइंट के बिल्ट-इन पार्सर (यदि एक है) का उपयोग करता है। इसलिए आपको इसे करने के लिए jQuery की आवश्यकता नहीं है, लेकिन सादे पुराने जावास्क्रिप्ट की दो लाइनों के रूप में । यदि कोई अंतर्निहित पार्सर नहीं है, तो jQuery मदद नहीं करेगा।
रॉब

1
@RobG वास्तव में jQuery DOM का उपयोग करता है, बिल्ट-इन पार्सर का नहीं।
Qix - मोनासा

11
@ Qix- तब आप बेहतर ढंग से प्रलेखन के लेखकों को बताएंगे: " jQuery.parseXML ब्राउज़र के मूल पार्सिंग फ़ंक्शन का उपयोग करता है ... "। स्रोत: jQuery.parseXML ()
RobG

6
मेम के सवाल ( meta.stackexchange.com/questions/19478/the-many-memes-of-meta/… ) से यहां आने के बाद , मुझे लगता है कि जवाब में से एक है 'का उपयोग करें jQuery'
Jorn

221

हालाँकि, जो उत्तर आप HTML को regexes के साथ पार्स नहीं कर सकते, वे सही हैं, वे यहां लागू नहीं होते हैं। ओपी सिर्फ एक HTML टैग को रेगेक्स के साथ पार्स करना चाहता है, और यह एक ऐसी चीज है जिसे नियमित अभिव्यक्ति के साथ किया जा सकता है।

सुझाया गया रेगेक्स गलत है, हालांकि:

<([a-z]+) *[^/]*?>

यदि आप रेगेक्स में कुछ जोड़ते हैं, तो पीछे जाकर इसे मूर्खतापूर्ण चीजों से मेल खाने के लिए मजबूर किया जा सकता है <a >>, जैसे [^/]कि बहुत अधिक अनुमति है। यह भी ध्यान दें कि <space>*[^/]*यह बेमानी है, क्योंकि [^/]*रिक्त स्थान का मिलान भी हो सकता है।

मेरा सुझाव होगा

<([a-z]+)[^>]*(?<!/)>

जहां (?<! ... )(Perl regexes में) नकारात्मक रूप है। इसमें लिखा है "a <, फिर एक शब्द, फिर कुछ भी ऐसा नहीं है>, जिसमें से अंतिम नहीं हो सकता है a /, उसके बाद>"।

ध्यान दें कि यह <a/ >(मूल रेगेक्स की तरह) चीजों को अनुमति देता है , इसलिए यदि आप कुछ अधिक प्रतिबंधक चाहते हैं, तो आपको रिक्त स्थान से अलग विशेषता जोड़े से मेल खाने के लिए एक रेगेक्स बनाने की आवश्यकता है।


29
+1 यह ध्यान देने के लिए कि प्रश्न पूर्ण (X) HTML को पार्स करने के बारे में नहीं है, यह मिलान (X) HTML के खुले टैग के बारे में है।
लार्स

10
कुछ और जवाब जो सबसे ज्यादा नजरअंदाज करते हैं, वह यह है कि HTML पार्सर HTML के कुछ हिस्सों में इसके क्रियान्वयन के लिए नियमित अभिव्यक्ति का बहुत अच्छा उपयोग कर सकता है, और मुझे आश्चर्य होगा कि अधिकांश पार्सर ऐसा नहीं करते।
थायने

@ थायने बिल्कुल। व्यक्तिगत टैग पार्स करते समय, एक नियमित अभिव्यक्ति नौकरी के लिए सही उपकरण है। यह काफी हास्यास्पद है कि एक उचित जवाब खोजने के लिए पेज को आधा नीचे स्क्रॉल करना पड़ता है। स्वीकृत उत्तर गलत है क्योंकि इसमें लेक्सिंग और पार्सिंग मिला हुआ है।
कास्परड

2
यहां दिया गया उत्तर विफल हो जाएगा जब एक विशेषता मान में '>' या '/' वर्ण होता है।
मार्टिन एल

यह HTML युक्त टिप्पणियों या CData अनुभागों पर गलत तरीके से काम करेगा। यह भी सही ढंग से काम नहीं करेगा अगर एक उद्धृत विशेषता में एक >चरित्र होता है । मैं मानता हूं कि ओपी सुझाव एक रेक्स के साथ क्या किया जा सकता है, लेकिन यहां प्रस्तुत एक व्यक्ति सरल है।
जैकब जूल

183

प्रयत्न:

<([^\s]+)(\s[^>]*?)?(?<!/)>

यह आपके समान है, लेकिन अंतिम >स्लैश के बाद नहीं होना चाहिए, और यह भी स्वीकार करता है h1


107
<a href="foo" title="5> 3 "> Oops </a>
गैरेथ

21
यह बहुत सच है, और मैंने इसके बारे में सोचा था, लेकिन मैंने माना कि >प्रतीक ठीक से & gt; से बच गया है;
कोबी

65
>एक विशेषता मान में मान्य है। वास्तव में, 'कैनोनिकल एक्सएमएल' क्रमांकन में आपको उपयोग नहीं करना चाहिए &gt;। (जो पूरी तरह से प्रासंगिक नहीं है, इस बात पर जोर देने के अलावा कि >एक विशेषता मूल्य बिल्कुल भी असामान्य बात नहीं है।)
बॉब

5
@ कोबी: एक्सप्लायंटेशन मार्क (जिसे आपने अंतिम छोर दिया है) का मतलब है रेक्सएक्सप?
मार्को डेमायो

6
@ बॉबिन: क्या आपको यकीन है? मुझे अब समझ में नहीं आ रहा है, इसलिए यह वैध HTML भी है:<div title="this tag is a <div></div>">hello</div>
मार्को डेमायो

179

सूर्य त्ज़ु, एक प्राचीन चीनी रणनीतिकार, सामान्य और दार्शनिक, ने कहा:

यह कहा जाता है कि यदि आप अपने दुश्मनों को जानते हैं और खुद को जानते हैं, तो आप एक भी नुकसान के बिना सौ लड़ाई जीत सकते हैं। यदि आप केवल अपने आप को जानते हैं, लेकिन अपने प्रतिद्वंद्वी को नहीं, तो आप जीत सकते हैं या हार सकते हैं। यदि आप न तो खुद को और न ही अपने दुश्मन को जानते हैं, तो आप हमेशा अपने आप को खतरे में डालेंगे।

इस स्थिति में आपका शत्रु HTML है और आप स्वयं या रीजेक्स हैं। आप अनियमित रेगेक्स के साथ भी पर्ल हो सकते हैं। जानिए HTML खुद को जानें।

मैंने HTML की प्रकृति का वर्णन करते हुए हाइकु की रचना की है।

HTML has
complexity exceeding
regular language.

मैंने पर्ल में रेगेक्स की प्रकृति का वर्णन करते हुए हाइकु की रचना भी की है।

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>

153
<?php
$selfClosing = explode(',', 'area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed');

$html = '
<p><a href="#">foo</a></p>
<hr/>
<br/>
<div>name</div>';

$dom = new DOMDocument();
$dom->loadHTML($html);
$els = $dom->getElementsByTagName('*');
foreach ( $els as $el ) {
    $nodeName = strtolower($el->nodeName);
    if ( !in_array( $nodeName, $selfClosing ) ) {
        var_dump( $nodeName );
    }
}

आउटपुट:

string(4) "html"
string(4) "body"
string(1) "p"
string(1) "a"
string(3) "div"

मूल रूप से केवल स्वयं के समापन वाले तत्व नोड नामों को परिभाषित करें, पूरे HTML स्ट्रिंग को एक डोम लाइब्रेरी में लोड करें, सभी तत्वों को पकड़ो, उन लोगों के माध्यम से लूप करें और उन लोगों को फ़िल्टर करें जो स्वयं समापन नहीं हैं और उन पर काम करते हैं।

मुझे यकीन है कि आप पहले से ही अब तक जानते हैं कि आपको इस उद्देश्य के लिए regex का उपयोग नहीं करना चाहिए।


1
यदि आप वास्तविक XHTML के साथ काम कर रहे हैं तो getElementsByTagName NSको नाम स्थान के साथ संलग्न करें।
प्रात: काल

148

मैं इसके लिए आपकी सटीक आवश्यकता नहीं जानता, लेकिन यदि आप .NET का उपयोग भी कर रहे हैं, तो क्या आप एचटीएमएल एगिलिटी पैक का उपयोग नहीं कर सकते हैं ?

अंश:

यह एक .NET कोड लाइब्रेरी है जो आपको वेब से "HTML फ़ाइलों" को पार्स करने की अनुमति देता है। पार्सर "वास्तविक दुनिया" विकृत HTML के साथ बहुत सहिष्णु है।


137

आप >पहले एक से पहले नहीं चाहते हैं /। देखो यहाँ है कि कैसे करना है पर जानकारी के लिए। इसे नकारात्मक रूप में देखा जाता है।

हालाँकि, इसका एक भोली कार्यान्वयन <bar/></foo>इस उदाहरण दस्तावेज़ में मेल खाएगा

<foo><bar/></foo>

क्या आप उस समस्या पर थोड़ी और जानकारी प्रदान कर सकते हैं जिसे आप हल करने की कोशिश कर रहे हैं? क्या आप प्रोग्राम के माध्यम से टैग से पुनरावृति कर रहे हैं?


1
हां, मुझे यकीन है कि हूँ। वर्तमान में खुले सभी टैग का निर्धारण, फिर तुलना करें कि बंद टैग के खिलाफ एक अलग सरणी में। RegEx मेरे मस्तिष्क को चोट पहुँचाता है।
जेफ

122

W3C एक छद्म regexp रूप में पार्स करने की व्याख्या करता है:
W3C लिंक

के लिए वर लिंक का पालन करें QName, Sऔर Attributeअधिक स्पष्ट चित्र प्राप्त करने के लिए।
इसके आधार पर आप स्ट्रिपिंग टैग जैसी चीजों को संभालने के लिए एक बहुत अच्छा regexp बना सकते हैं।


5
यह एक psoedo regexp फॉर्म नहीं है, जो कि EBNF का एक रूप है, जैसा कि यहाँ निर्दिष्ट किया गया है: XML कल्पना, परिशिष्ट 6
Rob G

106

अगर आपको PHP के लिए इसकी आवश्यकता है:

पीएचपी डोम कार्यों ठीक से काम नहीं करेंगे जब तक कि यह ठीक से एक्सएमएल स्वरूपित है। कोई फर्क नहीं पड़ता कि उनका उपयोग बाकी मानव जाति के लिए कितना बेहतर है।

simplehtmldom अच्छा है, लेकिन मुझे यह थोड़ा बुरा लग रहा है, और यह काफी मेमोरी है [बड़े पृष्ठों पर दुर्घटनाग्रस्त हो जाएगा।]

मैंने कभी क्वेरिपथ का उपयोग नहीं किया है , इसलिए इसकी उपयोगिता पर टिप्पणी नहीं कर सकता।

एक और कोशिश करने के लिए मेरा DOMParser है जो संसाधनों पर बहुत हल्का है और मैं थोड़ी देर के लिए खुशी से उपयोग कर रहा हूं। जानने के लिए सरल और शक्तिशाली।

पायथन और जावा के लिए, इसी तरह के लिंक पोस्ट किए गए थे।

डाउनवोटर्स के लिए - मैंने केवल अपनी कक्षा तब लिखी थी जब XML पार्सर वास्तविक उपयोग का सामना करने में असमर्थ साबित हुआ था। धार्मिक उत्थान केवल उपयोगी उत्तरों को पोस्ट करने से रोकता है - चीजों को प्रश्न के परिप्रेक्ष्य में रखें, कृपया।


95

यहाँ समाधान है:

<?php
// here's the pattern:
$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*(\/>|>)/';

// a string to parse:
$string = 'Hello, try clicking <a href="#paragraph">here</a>
    <br/>and check out.<hr />
    <h2>title</h2>
    <a name ="paragraph" rel= "I\'m an anchor"></a>
    Fine, <span title=\'highlight the "punch"\'>thanks<span>.
    <div class = "clear"></div>
    <br>';

// let's get the occurrences:
preg_match_all($pattern, $string, $matches, PREG_PATTERN_ORDER);

// print the result:
print_r($matches[0]);
?>

इसे गहराई से जांचने के लिए, मैंने स्ट्रिंग ऑटो-क्लोजिंग टैग्स में प्रवेश किया:

  1. <hr />
  2. <br/>
  3. <br>

मैंने इसके साथ टैग भी दर्ज किए:

  1. एक विशेषता
  2. एक से अधिक विशेषताएँ
  3. विशेषताएँ जो मूल्य एकल उद्धरणों में या दोहरे उद्धरण चिह्नों में बंधी हैं
  4. एकल उद्धरण युक्त विशेषताएँ जब सीमांकक एक दोहरे उद्धरण और इसके विपरीत है
  5. "=" प्रतीक के पहले एक स्थान के साथ "व्याख्या", इसके बाद और इसके पहले दोनों।

क्या आपको ऐसी कोई चीज़ मिलनी चाहिए जो ऊपर अवधारणा के प्रमाण में काम नहीं करती है, मैं अपने कौशल में सुधार करने के लिए कोड का विश्लेषण करने में उपलब्ध हूं।

<EDIT> मैं यह भूल गया कि उपयोगकर्ता से सवाल स्व-समापन टैग के पार्सिंग से बचने के लिए था। इस मामले में पैटर्न सरल है, इस में बदल रहा है:

$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*>/';

उपयोगकर्ता @ridgerunner ने देखा कि पैटर्न बिना किसी मूल्य के अयोग्य विशेषताओं या विशेषताओं की अनुमति नहीं देता है । इस मामले में एक अच्छी ट्यूनिंग हमें निम्न पैटर्न लाती है:

$pattern = '/<(\w+)(\s+(\w+)(\s*\=\s*(\'|"|)(.*?)\\5\s*)?)*\s*>/';

</ संपादित करें>

पैटर्न को समझना

अगर किसी को पैटर्न के बारे में अधिक जानने में दिलचस्पी है, तो मैं कुछ लाइन प्रदान करता हूं:

  1. पहला उप-अभिव्यक्ति (\ w +) टैग नाम से मेल खाता है
  2. दूसरी उप-अभिव्यक्ति में एक विशेषता का पैटर्न होता है। यह द्वारा रचित है:
    1. एक या अधिक व्हाट्सएप \ _ +
    2. विशेषता का नाम (\ w +)
    3. शून्य या अधिक व्हॉट्सएप्स * (यह संभव है या नहीं, यहां खाली छोड़ना)
    4. "=" प्रतीक
    5. फिर से, शून्य या अधिक व्हाट्सएप
    6. विशेषता मान का सीमांकक, एक एकल या डबल उद्धरण ('| ")। पैटर्न में, एकल उद्धरण बच जाता है क्योंकि यह PHP स्ट्रिंग सीमांकक के साथ मेल खाता है। यह उप-अभिव्यक्ति कोष्ठक के साथ कैप्चर की जाती है, इसलिए इसे संदर्भित किया जा सकता है। फिर से विशेषता को बंद करने के लिए, इसलिए यह बहुत महत्वपूर्ण है।
    7. विशेषता का मूल्य, लगभग किसी भी चीज से मेल खाता है : (? *?); इस विशिष्ट वाक्यविन्यास में, लालची मैच (तारांकन के बाद प्रश्न चिह्न) का उपयोग करके, RegExp इंजन एक "लुक-फॉरवर्ड"-समान ऑपरेटर को सक्षम करता है, जो कुछ भी मेल खाता है लेकिन इस उप-अभिव्यक्ति का अनुसरण करता है
    8. यहाँ मज़ेदार बात आती है: \ 4 भाग एक पश्च संचालक है , जो पैटर्न में पहले परिभाषित उप-अभिव्यक्ति को संदर्भित करता है, इस मामले में, मैं चौथे उप-अभिव्यक्ति की बात कर रहा हूँ, जो पहली विशेषता सीमांकक है।
    9. शून्य या अधिक व्हाट्सएप *
    10. विशेषता उप-अभिव्यक्ति यहाँ समाप्त होती है, तारांकन द्वारा दिए गए शून्य या अधिक संभावित घटनाओं के विनिर्देशन के साथ।
  3. फिर, चूंकि ">" प्रतीक से पहले कोई टैग व्हॉट्सएप के साथ समाप्त हो सकता है, शून्य या अधिक व्हाट्सएप का मिलान \ _ * उपपट्ट से होता है।
  4. मिलान करने का टैग एक साधारण ">" प्रतीक, या एक संभावित XHTML बंद के साथ समाप्त हो सकता है, जो इससे पहले स्लैश का उपयोग करता है: (/>> |>)। स्लैश, निश्चित रूप से बच गया है क्योंकि यह नियमित अभिव्यक्ति सीमांकक के साथ मेल खाता है।

छोटा टिप: इस कोड का बेहतर विश्लेषण करने के लिए आवश्यक स्रोत कोड को देखना आवश्यक है क्योंकि मैंने बचने के लिए कोई HTML विशेष वर्ण प्रदान नहीं किया है।


12
बिना मूल्य वाले विशेषताओं वाले वैध टैग से मेल नहीं खाता, अर्थात <option selected>। इसके अलावा वैध टैग से अछूता विशेषता मानों से मेल नहीं खाता, अर्थात <p id=10>
सवार

1
@ridgerunner: आपकी टिप्पणी के लिए बहुत बहुत धन्यवाद। उस स्थिति में पैटर्न को थोड़ा बदलना होगा: $ पैटर्न = '/ ((\ w +) (\ s + (\ w +)) (\ s * \ _ \ _ s * (\' | ") | (।?) *? \ _ 5 \ s *);) * \ s *> / '; मैंने इसका परीक्षण किया और बिना किसी मूल्य के गैर-उद्धृत विशेषताओं या विशेषताओं के मामले में काम करता है।
इमानुएल डेल ग्रांडे

टैग नाम से पहले स्पेस के बारे में कैसे: < a href="http://wtf.org" >मुझे पूरा यकीन है कि यह कानूनी है, लेकिन आप इसे मेल नहीं खाते।
फ्लोरिस

7
कोई सॉरी नहीं है, व्हाट्सएप पहले एक टैग्नैम अवैध है। परे "बहुत यकीन है" क्यों आप अपनी आपत्ति के कुछ सबूत प्रदान नहीं करते हैं? यहाँ मेरा, w3.org/TR/xml11/#sec-starttags XML 1.1 को संदर्भित किया गया है, और आप HTML 4, 5 और XHTML के लिए समान पा सकते हैं, क्योंकि W3C सत्यापन भी चेतावनी देगा यदि आप एक परीक्षण करते हैं। इधर-उधर बहुत से अन्य ब्ला-ब्ला-कवियों के रूप में, मुझे अभी भी कोई भी बुद्धिमान तर्क नहीं मिला, इसके अलावा मेरे उत्तरों में से कुछ सौ माइनस, यह प्रदर्शित करने के लिए कि प्रश्न में निर्दिष्ट अनुबंध के नियमों के अनुसार मेरा कोड कहां विफल रहता है । मैं केवल उनका स्वागत करूंगा।
इमानुएल डेल ग्रांडे

@ridgerunner बेशक आपकी टिप्पणी बुद्धिमान और स्वागत योग्य थी।
इमानुएल डेल ग्रांडे

91

जब भी मुझे किसी HTML दस्तावेज़ से किसी चीज़ को जल्दी निकालने की आवश्यकता होती है, तो मैं इसे XML में बदलने के लिए Tidy का उपयोग करता हूं और फिर मुझे जो चाहिए, उसे प्राप्त करने के लिए XPath या XSLT का उपयोग करता है। आपके मामले में, कुछ इस तरह:

//p/a[@href='foo']

89

मैंने पहले एक ओपन सोर्स टूल का इस्तेमाल किया था जिसे HTMLParser कहा जाता है । यह विभिन्न तरीकों से HTML को पार्स करने के लिए डिज़ाइन किया गया है और उद्देश्य को काफी अच्छी तरह से प्रस्तुत करता है। यह HTML को अलग-अलग टैरिनोड के रूप में पार्स कर सकता है और आप नोड से विशेषताओं को प्राप्त करने के लिए आसानी से इसके एपीआई का उपयोग कर सकते हैं। इसे देखें और देखें कि क्या यह आपकी मदद कर सकता है।


84

मुझे नियमित भावों के साथ HTML पार्स करना पसंद है। मैं बेवकूफ HTML को पार्स करने का प्रयास नहीं करता जो जानबूझकर टूटी हुई है। यह कोड मेरा मुख्य पार्सर (पर्ल संस्करण) है:

$_ = join "",<STDIN>; tr/\n\r \t/ /s; s/</\n</g; s/>/>\n/g; s/\n ?\n/\n/g;
s/^ ?\n//s; s/ $//s; print

इसे HTMLsplit कहा जाता है, HTML को लाइनों में विभाजित करता है, प्रत्येक लाइन पर एक टैग या टेक्स्ट का हिस्सा होता है। इसके बाद अन्य टेक्स्ट टूल्स और स्क्रिप्ट जैसे कि grep , sed , Perl आदि के साथ लाइनों को आगे प्रोसेस किया जा सकता है ।

यदि आप भारी वेब पृष्ठों को संसाधित करना चाहते हैं, तो मेरे स्लरप-एवरीथिंग-प्रथम पर्ल स्क्रिप्ट को एक अच्छी स्ट्रीमिंग चीज़ में फिर से जोड़ना सरल है। लेकिन यह वास्तव में आवश्यक नहीं है।

मुझे यकीन है कि मैं इसके लिए नीच हो जाऊंगा।

HTML स्प्लिट


मेरी अपेक्षा के विरुद्ध इसमें कुछ उतार-चढ़ाव आए, इसलिए मैं कुछ बेहतर नियमित अभिव्यक्ति सुझाता हूँ:

/(<.*?>|[^<]+)\s*/g    # get tags and text
/(\w+)="(.*?)"/g       # get attibutes

वे XML / XHTML के लिए अच्छे हैं।

मामूली बदलावों के साथ, यह गन्दा HTML के साथ सामना कर सकता है ... या पहले HTML -> XHTML में परिवर्तित कर सकता है।


नियमित अभिव्यक्ति लिखने का सबसे अच्छा तरीका लेक्स / याक शैली में है, न कि अपारदर्शी वन-लाइनर्स के रूप में या बहु-पंक्ति राक्षसी टिप्पणी की। मैंने ऐसा यहाँ नहीं किया, फिर भी; इन लोगों को मुश्किल से इसकी जरूरत है।


35
"मैं बेवकूफ HTML को पार्स करने का प्रयास नहीं करता जो जानबूझकर टूट गया है।" आपके कोड को अंतर कैसे पता चलता है?
केविन पैंको

वैसे यह ज्यादा मायने नहीं रखता कि HTML टूटी है या नहीं। बात अभी भी HTML को टैग और टेक्स्ट में विभाजित करेगी। केवल एक चीज जो इसे गलत कर सकती है वह यह है कि लोगों को पाठ या विशेषताओं में अपठित <या> वर्ण शामिल हैं। व्यवहार में, मेरा छोटा HTML फाड़नेवाला अच्छी तरह से काम करता है। मुझे एक विशाल राक्षसी उत्तराधिकार की आवश्यकता नहीं है। सरल उपाय हर किसी के लिए नहीं हैं ...!
सैम वाटकिंस

मैंने एक्सएमएल / एक्सएचटीएमएल के लिए टैग, पाठ और विशेषताओं को निकालने के लिए कुछ सरल रीजैक्स जोड़ दिए।
सैम वॉटकिंस

(गुण बग प्राप्त करें) /(\w+)="(.*?)"/दोहरे उद्धरणों को मानता है। यह एकल उद्धरणों में मूल्यों को याद करेगा। Html वर्जन 4 में और पहले के अनक्लोस्ड वैल्यू की अनुमति है, अगर यह एक साधारण शब्द है।
डेविड एंडरसन

(विशेषताएँ बग 2 प्राप्त करें) /(\w+)="(.*?)"/एक विशेषता के भीतर एक विशेषता की तरह दिखने वाले पाठ से मिथ्या मिलान कर सकते हैं <img title="Nope down='up' for aussies" src="..." />। यदि विश्व स्तर पर लागू किया जाता है, तो यह साधारण पाठ या HTML टिप्पणियों में भी ऐसी चीजों से मेल खाएगा।
डेविड एंडरसन

74

यहाँ एक PHP आधारित पार्सर है जो कुछ ungodly regex का उपयोग करके HTML को पार्स करता है। इस परियोजना के लेखक के रूप में, मैं आपको बता सकता हूं कि HTML को रेगेक्स के साथ पार्स करना संभव है, लेकिन कुशल नहीं है। यदि आपको सर्वर-साइड समाधान की आवश्यकता है (जैसा कि मैंने अपने wp-Typography WordPress plugin के लिए किया था ), यह काम करता है।


1
htmlawed एक और PHP प्रोजेक्ट है जो HTML को फ़िल्टर करने, कन्वर्ट करने आदि के लिए पार्स करता है। यदि आपके पास इसका पता चल जाए तो कुछ अच्छा कोड है!
user594694

नहीं, आप HTML को regex के साथ पार्स नहीं कर सकते । लेकिन कुछ सबसेट के लिए, यह काम कर सकता है
मीराबिलोस 17

71

HTML को BBCode के साथ बदलने के लिए कुछ अच्छे रीगेक्स हैं । आप सभी के लिए, यह कहना, ध्यान दें कि वह HTML को पूरी तरह से पार्स करने की कोशिश नहीं कर रहा है, सिर्फ इसे साफ करने के लिए। वह शायद उन टैगों को मारना बंद कर सकता है जो उसके सरल "पार्सर" समझ नहीं सकते।

उदाहरण के लिए:

$store =~ s/http:/http:\/\//gi;
$store =~ s/https:/https:\/\//gi;
$baseurl = $store;

if (!$query->param("ascii")) {
    $html =~ s/\s\s+/\n/gi;
    $html =~ s/<pre(.*?)>(.*?)<\/pre>/\[code]$2\[\/code]/sgmi;
}

$html =~ s/\n//gi;
$html =~ s/\r\r//gi;
$html =~ s/$baseurl//gi;
$html =~ s/<h[1-7](.*?)>(.*?)<\/h[1-7]>/\n\[b]$2\[\/b]\n/sgmi;
$html =~ s/<p>/\n\n/gi;
$html =~ s/<br(.*?)>/\n/gi;
$html =~ s/<textarea(.*?)>(.*?)<\/textarea>/\[code]$2\[\/code]/sgmi;
$html =~ s/<b>(.*?)<\/b>/\[b]$1\[\/b]/gi;
$html =~ s/<i>(.*?)<\/i>/\[i]$1\[\/i]/gi;
$html =~ s/<u>(.*?)<\/u>/\[u]$1\[\/u]/gi;
$html =~ s/<em>(.*?)<\/em>/\[i]$1\[\/i]/gi;
$html =~ s/<strong>(.*?)<\/strong>/\[b]$1\[\/b]/gi;
$html =~ s/<cite>(.*?)<\/cite>/\[i]$1\[\/i]/gi;
$html =~ s/<font color="(.*?)">(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<font color=(.*?)>(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<link(.*?)>//gi;
$html =~ s/<li(.*?)>(.*?)<\/li>/\[\*]$2/gi;
$html =~ s/<ul(.*?)>/\[list]/gi;
$html =~ s/<\/ul>/\[\/list]/gi;
$html =~ s/<div>/\n/gi;
$html =~ s/<\/div>/\n/gi;
$html =~ s/<td(.*?)>/ /gi;
$html =~ s/<tr(.*?)>/\n/gi;

$html =~ s/<img(.*?)src="(.*?)"(.*?)>/\[img]$baseurl\/$2\[\/img]/gi;
$html =~ s/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/\[url=$baseurl\/$2]$4\[\/url]/gi;
$html =~ s/\[url=$baseurl\/http:\/\/(.*?)](.*?)\[\/url]/\[url=http:\/\/$1]$2\[\/url]/gi;
$html =~ s/\[img]$baseurl\/http:\/\/(.*?)\[\/img]/\[img]http:\/\/$1\[\/img]/gi;

$html =~ s/<head>(.*?)<\/head>//sgmi;
$html =~ s/<object>(.*?)<\/object>//sgmi;
$html =~ s/<script(.*?)>(.*?)<\/script>//sgmi;
$html =~ s/<style(.*?)>(.*?)<\/style>//sgmi;
$html =~ s/<title>(.*?)<\/title>//sgmi;
$html =~ s/<!--(.*?)-->/\n/sgmi;

$html =~ s/\/\//\//gi;
$html =~ s/http:\//http:\/\//gi;
$html =~ s/https:\//https:\/\//gi;

$html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsi;
$html =~ s/\r\r//gi;
$html =~ s/\[img]\//\[img]/gi;
$html =~ s/\[url=\//\[url=/gi;

15
यह मत करो। कृप्या।
maletor

68

RegExp मेथड्स टू पार्स (x) HTML के प्रश्न के बारे में, कुछ सीमाओं के बारे में बात करने वाले सभी लोगों का उत्तर है: आपको इस शक्तिशाली हथियार के बल पर शासन करने के लिए पर्याप्त प्रशिक्षित नहीं किया गया है, क्योंकि NOBODY ने यहां पुनरावर्तन की बात की थी ।

एक RegExp-agnostic सहयोगी ने मुझे इस चर्चा को सूचित किया, जो निश्चित रूप से इस पुराने और गर्म विषय के बारे में वेब पर पहली बार नहीं है।

कुछ पोस्ट पढ़ने के बाद, पहली चीज जो मैंने की थी, वह इस धागे में "? R" स्ट्रिंग है। दूसरा "पुनरावृत्ति" के बारे में खोज करना था।
नहीं, पवित्र गाय, कोई मेल नहीं मिला।
चूंकि किसी ने मुख्य तंत्र का उल्लेख नहीं किया है, जिस पर एक पार्सर बनाया गया है, मुझे जल्द ही पता चल गया था कि किसी को भी बात नहीं मिली।

यदि एक (x) HTML पार्सर को पुनर्संरचना की आवश्यकता है, तो पुनरावृत्ति के बिना एक RegExp पार्सर उद्देश्य के लिए पर्याप्त नहीं है। यह एक साधारण निर्माण है।

RegExp की काली कला में महारत हासिल करना कठिन है , इसलिए हो सकता है कि आगे की संभावनाओं को छोड़ते हुए हम अपने व्यक्तिगत समाधान को एक हाथ में पकड़ने के लिए पूरी कोशिश कर रहे हों ... खैर, मुझे इस पर यकीन है :)

यहाँ जादू पैटर्न है:

$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";

कर के देखो।
यह एक PHP स्ट्रिंग के रूप में लिखा गया है, इसलिए "s" संशोधक कक्षाओं को शामिल करता है जिसमें newlines शामिल हैं।
यहाँ एक है पीएचपी पुस्तिका पर नमूना टिप्पणी मैं जनवरी को लिखा था: संदर्भ

(ध्यान रखें, उस नोट में मैंने गलत तरीके से "m" संशोधक का उपयोग किया था; इसे मिटा दिया जाना चाहिए, इसके बावजूद कि यह RegExp इंजन द्वारा खारिज कर दिया गया है, क्योंकि कोई ^ या $ लंगर इस्तेमाल नहीं किया गया था)।

अब, हम इस विधि की सीमाओं के बारे में अधिक सूचित दृष्टिकोण से बोल सकते हैं:

  1. RegExp इंजन के विशिष्ट कार्यान्वयन के अनुसार, पुनर्संरभित किए गए नेस्टेड पैटर्न की संख्या में सीमा हो सकती है , लेकिन यह उपयोग की जाने वाली भाषा पर निर्भर करती है
  2. हालाँकि दूषित (x) HTML गंभीर त्रुटियों में ड्राइव नहीं करता है, यह स्वच्छता नहीं है ।

किसी भी तरह यह केवल एक RegExp पैटर्न है, लेकिन यह बहुत सारे शक्तिशाली कार्यान्वयन के विकास की संभावना का खुलासा करता है।
मैंने इस पैटर्न को अपने ढांचे में बनाए गए टेम्पलेट इंजन के पुनरावर्ती वंशीय पार्सर को शक्ति देने के लिए लिखा था , और प्रदर्शन वास्तव में बहुत बढ़िया हैं, निष्पादन समय या स्मृति उपयोग (दोनों अन्य टेम्पलेट इंजन जो समान वाक्यविन्यास का उपयोग नहीं करते हैं) के साथ कुछ भी नहीं करने के लिए।


35
मैं इसे "रेगेक्स में डाल दूंगा जो विशेषताओं में अधिक से अधिक-अनुमति नहीं देता है" बिन। इसके खिलाफ जाँच करें <input value = "5> 3?" />
गैरेथ

68
यदि आप उत्पादन कोड में ऐसा कुछ डालते हैं, तो आपको अनुरक्षक द्वारा गोली मार दी जाएगी। एक जूरी उसे कभी दोषी नहीं ठहराती।
ऐहिलर्स

30
नियमित अभिव्यक्ति काम नहीं कर सकती क्योंकि परिभाषा के अनुसार वे पुनरावर्ती नहीं हैं। नियमित रूप से अभिव्यक्ति के लिए एक पुनरावर्ती ऑपरेटर जोड़ना मूल रूप से सीएफजी केवल खराब सिंटैक्स के साथ बनाता है। पहले से ही बहिष्कृत कार्यक्षमता के साथ बहने वाली किसी चीज़ में हिंसक सम्मिलित करने के बजाय पहली जगह में पुनरावर्ती होने के लिए डिज़ाइन की गई चीज़ का उपयोग क्यों न करें?
वेलबॉग जूल 6'10

16
मेरी आपत्ति कार्यक्षमता में से एक नहीं है यह निवेश किए गए समय में से एक है। RegEx के साथ समस्या यह है कि जब तक आप cutsey को एक लाइनर पोस्ट करते हैं तब तक यह प्रतीत होता है कि आपने कुछ और अधिक कुशलता से किया था ("कोड की एक पंक्ति देखें!")। और निश्चित रूप से किसी ने आधे घंटे (या 3) का उल्लेख नहीं किया है जो उन्होंने अपनी चीट-शीट के साथ बिताए थे और (उम्मीद है) इनपुट के हर संभव क्रमांकन का परीक्षण कर रहे थे। और एक बार जब आप सभी को पा लेते हैं, जब अनुचर को पता लगाने या कोड को मान्य करने के लिए जाता है, तो वे इसे देख नहीं सकते हैं और देख सकते हैं कि यह सही है। अभिव्यक्ति को अलग करना होगा और अनिवार्य रूप से इसे फिर से सभी पर फिर से
लिखना होगा

15
... यह जानने के लिए कि यह अच्छा है। और ऐसा उन लोगों के साथ भी होगा जो रेगेक्स के साथ अच्छे हैं । और ईमानदारी से मुझे संदेह है कि अधिकांश लोग इसे अच्छी तरह से नहीं जानते होंगे। तो आप सबसे कुख्यात रखरखाव बुरे सपने में से एक लेते हैं और इसे पुनरावृत्ति के साथ जोड़ते हैं जो अन्य रखरखाव दुःस्वप्न है और मुझे खुद को लगता है कि मुझे अपने प्रोजेक्ट पर वास्तव में जो चाहिए वह किसी से कम चालाक नहीं है। लक्ष्य कोड लिखना है जो खराब प्रोग्रामर बिना कोड आधार को बनाए रख सकते हैं। मुझे पता है कि यह कम से कम आम भाजक को कोड करने के लिए है। लेकिन उत्कृष्ट प्रतिभा को काम पर
रखना

62

जैसा कि बहुत से लोग पहले ही बता चुके हैं, HTML एक नियमित भाषा नहीं है, जिससे उसे पार्स करना बहुत मुश्किल हो जाए। इसका मेरा समाधान यह है कि इसे एक नियमित कार्यक्रम में बदलकर एक सुव्यवस्थित कार्यक्रम का उपयोग किया जाए और फिर परिणामों का उपभोग करने के लिए XML पार्सर का उपयोग किया जाए। इसके लिए बहुत सारे अच्छे विकल्प हैं। मेरा प्रोग्राम जावा का उपयोग करके jtidy लाइब्रेरी के साथ लिखा गया है ताकि HTML को XML में बदल दिया जाए और फिर परिणाम में xpath को Javaen कर दिया जाए।


61
<\s*(\w+)[^/>]*>

भागों की व्याख्या की:

<: शुरू चरित्र

\s*: इसमें टैग नाम (बदसूरत लेकिन संभव) से पहले व्हाट्सएप हो सकता है।

(\w+): टैग में अक्षर और संख्याएं (h1) हो सकती हैं। वैसे, \w'_' से भी मेल खाता है, लेकिन इससे मुझे अनुमान नहीं है। यदि इसके बजाय जिज्ञासु उपयोग ([a-zA-Z0-9] +)।

[^/>]*: बंद करने तक >और कुछ भी/>

>: समापन >

असंबंधित

और उन साथियों को जो नियमित अभिव्यक्ति को कम कहते हैं, वे केवल नियमित भाषाओं के समान शक्तिशाली हैं:

एक n बा n बा जो n नियमित नहीं है और संदर्भ मुक्त भी नहीं है, के साथ मिलान किया जा सकता है^(a+)b\1b\1$

बैकफ़्रेन्सिंग FTW !


@GlitchMr, यही उनकी बात थी। आधुनिक नियमित अभिव्यक्ति तकनीकी रूप से नियमित नहीं हैं, और न ही उनके होने का कोई कारण है।
alanaktion

3
@alanaktion: "आधुनिक" नियमित अभिव्यक्तियाँ (पढ़ें: पर्ल एक्सटेंशन के साथ) मेल नहीं कर सकता O(MN)(एम नियमित अभिव्यक्ति लंबाई, एन पाठ लंबाई होने के नाते)। Backreferences उसी के कारणों में से एक हैं। Awk में कार्यान्वयन का बैकरेफेरेंस नहीं है और O(MN)समय के भीतर सब कुछ मेल खाता है ।
कोनराड बोरोस्की

56

यदि आप बस उन टैग्स को खोजने की कोशिश कर रहे हैं (पार्सिंग की महत्वाकांक्षाओं के बिना) इस नियमित अभिव्यक्ति की कोशिश करें:

/<[^/]*?>/g

मैंने इसे 30 सेकंड में लिखा था, और यहाँ परीक्षण किया: http://gskinner.com/RegExr/

यह आपके द्वारा बताए गए टैगों के प्रकारों से मेल खाता है, जबकि आपके द्वारा बताए गए प्रकारों को अनदेखा करना चाहते थे।


2
मुझे लगता है कि आप के \/>बजाय मतलब है \\>
जस्टिन मॉर्गन

नहीं, बस \>मेरा मतलब है; मुझे अपने मूल पद की नियमित अभिव्यक्ति को संपादित करने का कभी मतलब नहीं था।
लोनी बेस्ट

2
FYI करें, आपको कोण कोष्ठक से बचने की आवश्यकता नहीं है। बेशक, इससे उन्हें बचने का कोई नुकसान नहीं है, लेकिन आप जिस भ्रम से बच सकते हैं उसे देखें। ;)
एलन मूर

मैं कभी-कभी अनावश्यक रूप से बच जाता हूं जब मैं अनिश्चित होता हूं कि कुछ विशेष चरित्र है या नहीं। मैंने उत्तर संपादित किया है; यह समान लेकिन अधिक संक्षिप्त काम करता है।
लोनी बेस्ट

अब इसे देखते हुए, मुझे नहीं पता कि मुझे लगा कि आपका मतलब क्या है \/, क्योंकि यह आवश्यकताओं के बिल्कुल विपरीत होगा। शायद मुझे लगा कि आप एक नकारात्मक फ़िल्टर पैटर्न प्रदान कर रहे हैं।
जस्टिन मॉर्गन

54

ऐसा लगता है कि आप अंत में "/" के बिना टैग से मिलान करने का प्रयास कर रहे हैं। इसे इस्तेमाल करे:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>

8
यह काम नहीं करता। इनपुट '<xa = "<b>" /> <y> के लिए मिलान x और y हैं, हालांकि x को समाप्त कर दिया गया है।
ceving

51

यह सच है कि जब प्रोग्रामिंग यह आम तौर पर HTML के साथ काम करते समय नियमित अभिव्यक्तियों के बजाय समर्पित पर्सर्स और एपीआई का उपयोग करने के लिए सबसे अच्छा है, खासकर अगर सटीकता सर्वोपरि है (उदाहरण के लिए, यदि आपके प्रसंस्करण में सुरक्षा निहितार्थ हो सकते हैं)। हालांकि, मैं एक हठधर्मी दृष्टिकोण के लिए नहीं कहता हूं कि एक्सएमएल-शैली मार्कअप को नियमित अभिव्यक्तियों के साथ कभी भी संसाधित नहीं किया जाना चाहिए। ऐसे मामले हैं जब नियमित अभिव्यक्ति नौकरी के लिए एक महान उपकरण है, जैसे कि एक पाठ संपादक में एक बार संपादन करना, टूटी हुई एक्सएमएल फ़ाइलों को ठीक करना, या ऐसे फ़ाइल स्वरूपों से निपटना जो दिखने में समान हैं लेकिन काफी एक्सएमएल नहीं हैं। कुछ मुद्दों के बारे में पता होना चाहिए, लेकिन वे insurmountable या आवश्यक रूप से प्रासंगिक नहीं हैं।

<([^>"']|"[^"]*"|'[^']*')*>जैसा कि मैंने अभी उल्लेख किया है जैसे मामलों में एक साधारण रेगेक्स आमतौर पर काफी अच्छा होता है। यह एक भोली समाधान है, सभी बातों पर विचार किया गया है, लेकिन यह सही ढंग >से विशेषता मूल्यों में अनएन्कोडेड प्रतीकों की अनुमति देता है। यदि आप खोज रहे हैं, जैसे, एक tableटैग, तो आप इसे रूप में अनुकूलित कर सकते हैं </?table\b([^>"']|"[^"]*"|'[^']*')*>

बस एक और अधिक "उन्नत" HTML रेगेक्स की तरह क्या होगा की भावना देने के लिए, निम्नलिखित वास्तविक दुनिया ब्राउज़र व्यवहार और HTML5 पार्सिंग एल्गोरिथ्म का अनुकरण करने का काफी सम्मानजनक काम करता है:

</?([A-Za-z][^\s>/]*)(?:=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)|[^>])*(?:>|$)

निम्नलिखित एक्सएमएल टैग की काफी सख्त परिभाषा से मेल खाता है (हालांकि यह एक्सएमएल नामों में अनुमत यूनिकोड वर्णों के पूर्ण सेट के लिए जिम्मेदार नहीं है):

<(?:([_:A-Z][-.:\w]*)(?:\s+[_:A-Z][-.:\w]*\s*=\s*(?:"[^"]*"|'[^']*'))*\s*/?|/([_:A-Z][-.:\w]*)\s*)>

दी गई, ये आसपास के संदर्भ और कुछ बढ़त के मामलों के लिए जिम्मेदार नहीं हैं, लेकिन यहां तक ​​कि इस तरह की चीजों से निपटा जा सकता है यदि आप वास्तव में चाहते थे (उदाहरण के लिए, दूसरे रेगेक्स के मैचों के बीच खोज करके)।

दिन के अंत में, नौकरी के लिए सबसे उपयुक्त उपकरण का उपयोग करें, यहां तक ​​कि उन मामलों में भी जब यह उपकरण एक रेक्सक्स होता है।


49

यद्यपि यह उस उद्देश्य के लिए नियमित अभिव्यक्तियों का उपयोग करने के लिए उपयुक्त और प्रभावी नहीं है, कभी-कभी नियमित अभिव्यक्तियाँ सरल मैच समस्याओं के लिए त्वरित समाधान प्रदान करती हैं और मेरे विचार में यह तुच्छ कार्यों के लिए नियमित अभिव्यक्तियों का उपयोग करने के लिए भयावह नहीं है।

स्टीवन लेविथान द्वारा लिखित अंतरतम HTML तत्वों के मिलान के बारे में एक निश्चित ब्लॉग पोस्ट है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.