DanLevy.net

प्रश्नोत्तरी: रेगुलर एक्सप्रेशन में महारत

क्या आप जंगली रेगैक्स को काबू कर सकते हैं?

कुछ Regular Expressions से जूझने के लिए तैयार हैं? 🤼‍♂️

RegEx ज्ञान को परखें उन प्रश्नों से जो बुनियादी पैटर्न, क्वांटिफ़ायर, समूह और उन चतुर लुक‑अराउंड असर्शन को कवर करते हैं। सरल स्ट्रिंग मिलान से लेकर जटिल पैटर्न वैधता तक – क्या आप सही रेगेक्स पहचान सकते हैं?

क्या मिलते हैं?

'cat CAT Cat'.match(/cat/g)

यह पैटर्न g का उपयोग करता है, लेकिन i नहीं:

  • g सभी मिलान खोजता है
  • i के बिना, मिलान केस‑सेंसिटिव होता है

i फ़्लैग के बिना, केवल लोअरकेस “cat” ही मेल खाता है।

यह विशेष रूप से उपयोगी है जब उपयोगकर्ता इनपुट या HTML से निपटना हो जहाँ केस बदल सकता है।

RegExp फ़्लैग्स के बारे में और जानें

यह कोड क्या लौटाएगा?

const words = ['cat', 'hat', 'what', 'bat'];
words.filter(word => word.match(/^[ch]at/))

/^[ch]at/ पैटर्न उन स्ट्रिंग्स से मेल खाता है जो:

  • शुरुआत (^) में ‘c’ या ‘h’ में से कोई एक हो (यह [ch] का अर्थ है - एक कैरेक्टर क्लास जो एक अक्षर मिलाता है)
  • इसके बाद ठीक‑ठाक ‘at’ हो

इसलिए केवल “cat” और “hat” इस पैटर्न से मेल खाते हैं। filter() मेथड केवल मेल खाने वाले तत्वों को रखता है।

MDN पर कैरेक्टर क्लास के बारे में अधिक जानें

यह क्या मैच करेगा?

'<div>Hello</div><div>World</div>'.match(/<div>.*?<\/div>/g)

/<div>.*?<\/div>/g पैटर्न *? के साथ नॉन-ग्रीडी मैचिंग का उपयोग करता है, जिसका अर्थ है:

  • <div> से मिलाएँ
  • किसी भी अक्षर (.*) को मिलाएँ लेकिन यथासंभव कम (?)
  • </div> मिलने तक
  • g फ़्लैग सभी occurrences को मैच करता है

यदि ? न हो तो ग्रीडी .* पहले <div> से लेकर आखिरी </div> तक सब कुछ मैच करेगा, जिससे एक बड़ा मैच मिलेगा। ? के साथ यह प्रत्येक जोड़ी को अलग‑अलग मैच करता है।

greedy vs lazy matching के बारे में और जानें

यह क्या लौटाएगा?

'hello\nworld'.match(/\w+/g)

\w+ पैटर्न एक या अधिक शब्द अक्षरों से मेल खाता है। स्ट्रिंग में नई पंक्ति (\n) होने के बावजूद, \w मिलाता है:

  • अक्षर (a‑z, A‑Z)
  • संख्याएँ (0‑9)
  • अंडरस्कोर (_)

इसलिए नई पंक्ति शब्द सीमा की तरह काम करती है, और हमें दो मिलान मिलते हैं। यदि हम .* उपयोग करते तो यह डिफ़ॉल्ट रूप से नई पंक्ति से नहीं मिलता (इसके लिए s फ़्लैग चाहिए होता)।

मेटा‑कैरेक्टर के बारे में और जानें

यह क्या मैच करेगा?

'$100 and €50'.match(/\d+(?=[\$€])/g)

यह पैटर्न कोई मिलान नहीं खोजता, क्योंकि लुक-अहेड अंकों के बाद मुद्रा चिह्न जाँचता है, जबकि इनपुट में चिह्न पहले हैं। यदि आप ऐसे अंक चाहते हैं जिनसे पहले $ या € हो, तो लुक-बिहाइंड इस्तेमाल करें: /(?<=[\$€])\d+/g.

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

  • एक या अधिक अंक (\d+)
  • जिसके बाद ((?=...)) $ या € ([\$€])

क्योंकि ऐसे कोई नंबर नहीं हैं जिनके बाद मुद्रा चिन्ह हों (वे उनके पहले होते हैं), इसलिए कोई मैच नहीं मिलता।

लुक-अहेड असर्शन के बारे में अधिक जानें

क्या मेल करेगा?

'cat cats category'.match(/\bcat\b/g)

\b शब्द-सीमा (word boundary) दर्शाता है:

  • शब्द-अक्षर और गैर-शब्द-अक्षर के बीच।
  • स्ट्रिंग के आरंभ या अंत पर, यदि वहाँ शब्द-अक्षर हो।

इसलिए /\bcat\b/ केवल पूरा शब्द “cat” मिलाता है, दूसरे शब्द का हिस्सा नहीं।

  • ✅ “cat” (चारों ओर स्पेस)
  • ❌ “cats” (“cat” के बाद सीमा नहीं)
  • ❌ “category” (“cat” के बाद सीमा नहीं)

शब्द-सीमाओं के बारे में और जानें

आउटपुट क्या है?

'banana'.match(/a/g)

g (ग्लोबल) फ़्लैग match() के व्यवहार को बदलता है:

  • बिना g के: पहला मैच और कैप्चर ग्रुप लौटाता है
  • g के साथ: सभी मिलते‑जुलते स्ट्रिंग्स का एरे लौटाता है

इस मामले में, यह “banana” में सभी “a” की घटनाएँ खोजता है।

नोट: यदि आपको सभी मैच और कैप्चर ग्रुप दोनों चाहिए, तो matchAll() या लूप में exec() मेथड का उपयोग करें।

ग्लोबल फ़्लैग के बारे में और जानें

इस पैटर्न से क्या मेल खाता है?

'abc123 def456'.match(/(?<!abc)\d+/g)

नकारात्मक लुक‑बिहाइंड (?<!abc) यह सुनिश्चित करता है कि अंकों के पहले “abc” न हो:

  • ❌ “123” (इसके पहले “abc” है)
  • ✅ “23” (इसके पहले “abc1” है)
  • ✅ “456” (इसके पहले “def” है)

जावास्क्रिप्ट आधुनिक इंजन में लुक‑बिहाइंड एसेर्शन को सपोर्ट करता है। यह उदाहरण फिक्स्ड‑लेंथ लुक‑बिहाइंड का उपयोग करता है: abc हमेशा तीन अक्षर का होता है। वैरिएबल‑लेंथ लुक‑बिहाइंड अधिक जटिल इंजन‑विशिष्ट मामला है।

नोट: जावास्क्रिप्ट में लुक‑बिहाइंड सपोर्ट अपेक्षाकृत नया है। यदि आपको पुराने ब्राउज़र सपोर्ट करने हैं तो ब्राउज़र संगतता देखें।

यह क्या लौटाएगा?

'2029-12-31'.match(/(\d{4})-(\d{2})-(\d{2})/).slice(1)

पैटर्न में तीन कैप्चरिंग ग्रुप्स हैं:

  1. (\d{4}) वर्ष को कैप्चर करता है
  2. (\d{2}) महीने को कैप्चर करता है
  3. (\d{2}) दिन को कैप्चर करता है

match() बिना g फ़्लैग के लौटाता है:

  • इंडेक्स 0: पूरा मिलान
  • इंडेक्स 1+: कैप्चर ग्रुप्स

slice(1) एक आम ट्रिक है जिससे केवल कैप्चर ग्रुप्स मिलते हैं।

ग्रुप्स और कैप्चरिंग के बारे में और जानें

इसका परिणाम क्या होगा?

"123aBc".match(/^\d+(?![a-z])/ig)

i फ़्लैग के कारण (?![a-z]) अगले ASCII अक्षर को छोटे और बड़े दोनों केस में अस्वीकार करता है। ग्रीडी मिलान पहले 123 लेता है, a के पहले विफल होता है, फिर पीछे लौटकर 12 तक सिमटता है। अब अगला अक्षर 3 है, इसलिए एसेर्शन सफल होता है और परिणाम ["12"] मिलता है।

नकारात्मक लुक-अहेड के बारे में और जानें

क्या लौटाया जाता है?

'a,b,c'.split(/(?<=,)/)

पैटर्न /(?<=,)/ एक लुक-बिहाइंड है जो कॉमा के बाद मैच करता है:

  • a, (कॉमा के बाद)
  • b, (कॉमा के बाद)
  • c (कोई कॉमा नहीं)

लुक-बिहाइंड कॉमा को खपत नहीं करता, इसलिए कॉमा स्प्लिट परिणाम में पिछले भाग से जुड़ा रहता है.

यह तब उपयोगी होता है जब आप किसी स्ट्रिंग को उसके पहले आने वाले हिस्से के आधार पर विभाजित करना चाहते हैं बिना विभाजन कैरेक्टर(स) को खोए.

लुक-बिहाइंड एसेर्शन के बारे में और जानें

क्या मेल खाता है?

'$100'.match(/$\d+/)

विशेष अक्षरों को शाब्दिक रूप से मिलाने के लिए \ से एस्केप करना पड़ता है:

  • $ एक विशेष अक्षर है (स्ट्रिंग का अंत)
  • वास्तविक डॉलर साइन मिलाने के लिए, इसे एस्केप करें: \$

एस्केप करने वाले सामान्य अक्षर:

. * + ? ^ $ [ ] \ ( ) { } |

एस्केप किए बिना, कई विशेष अक्षरों के regex अर्थ होते हैं जो शायद आपकी इच्छा के अनुसार न हों।

विशेष अक्षरों को एस्केप करने के बारे में और जानें

क्या मिल रहा है?

'$100'.match(/(?<=\$)\d+/)

सकारात्मक लुक-बिहाइंड (?<=\$) सुनिश्चित करता है कि अंकों से पहले डॉलर चिह्न हो:

  • (?<=\$): डॉलर चिह्न के लिए लुक-बिहाइंड
  • \d+: एक या अधिक अंकों से मेल खाता है

लुक-बिहाइंड एसेर्शन अक्षरों को खपत नहीं करते; वे केवल यह जांचते हैं कि पहले क्या आया है। यह तब उपयोगी है जब आप कुछ ऐसा मिलाना चाहते हैं जो उसके पहले की स्थिति पर निर्भर हो, बिना पूर्व भाग को शामिल किए।

लुक-बिहाइंड एसेर्शन के बारे में अधिक जानें

क्या मिल रहा है?

'<b>bold</b>'.match(/<b>(.*?)<\/b>/).slice(1)

पैटर्न *? के साथ आलसी मिलान का उपयोग करता है:

  • <b>: खुलने वाला टैग मिलाएँ
  • (.*?): कोई भी अक्षर कैप्चर करें (आलसी)
  • </b>: बंद करने वाला टैग मिलाएँ

* के बाद ? इसे आलसी बनाता है, जिससे जितने कम से कम अक्षर संभव हों उतने ही मिलते हैं। यदि ? न हो तो यह लालची होगा और जितना संभव हो उतना मिलाएगा।

slice(1) केवल कैप्चर किए गए समूह को लौटाता है।

greedy vs lazy matching के बारे में और जानें

क्या मेल खाता है?

'😀 🙂'.match(/\p{Emoji}/gu)

u फ़्लैग सक्षम करता है:

  • यूनिकोड प्रॉपर्टी एस्केप्स (\p{...})
  • सरोगेट पेयर्स का सही हैंडलिंग

बिना u के, इमोजी और अन्य यूनिकोड कैरेक्टर सही ढंग से नहीं मिल सकते। पैटर्न \p{Emoji} उन कैरेक्टरों से मेल खाता है जिनकी यूनिकोड Emoji प्रॉपर्टी है। इस स्ट्रिंग में, इसका मतलब दो इमोजी पिक्टोग्राफ़ हैं।

नोट: यूनिकोड प्रॉपर्टी एस्केप्स के लिए Unicode-aware मोड आवश्यक है: u या v फ़्लैग का उपयोग करें।

Unicode मोड के बारे में अधिक जानें

पहले से ही माफ़ी! 😈
कौन सा पासवर्ड इस पैटर्न से मेल खाता है?

/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/

प्रोडक्शन में ऐसा कुछ भी न लिखें! 😅

यह पैटर्न कई पॉज़िटिव लुक‑अहेड्स का उपयोग करता है ताकि enforce किया जा सके:

  • कम से कम एक अपरकेस अक्षर: (?=.*[A-Z])
  • कम से कम एक लोअरकेस अक्षर: (?=.*[a-z])
  • कम से कम एक अंक: (?=.*\d)
  • कम से कम एक स्पेशल कैरेक्टर: (?=.*[!@#$%^&*])
  • न्यूनतम लंबाई 8: .{8,}

लुक‑अहेड्स पासवर्ड वैलिडेशन के लिए परफेक्ट हैं क्योंकि वे कई मानदंडों को बिना कैरेक्टर खाए चेक कर सकते हैं।

पासवर्ड वैलिडेशन पैटर्न के बारे में और पढ़ें

आपका प्रदर्शन कैसा रहा? 🧐

Regular Expressions को काबू में करना मुश्किल हो सकता है, लेकिन एक बार समझ आ जाए (और नई सिंटैक्स सीख लें) तो ये बेहद शक्तिशाली होते हैं। अभ्यास करते रहें, और आप जल्द ही रेगएक्स के माहिर बन जाएंगे! 🧙‍♂️

सारा रेगएक्स करने के बाद थोड़ा ब्रेक चाहिए?
हँ, याद रखें: ब्रेक स्किल्स के बाद ही लेना चाहिए!

और चुनौतियों को तोड़ने के लिए मेरे जिम पर जाएँ! 💪