जावास्क्रिप्ट में एक RegExp.escape फ़ंक्शन है?


442

मैं बस किसी भी संभावित स्ट्रिंग से बाहर एक नियमित अभिव्यक्ति बनाना चाहता हूं।

var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);

वहाँ के लिए एक विधि में बनाया गया है? यदि नहीं, तो लोग क्या उपयोग करते हैं? रूबी के पास है RegExp.escape। मुझे ऐसा नहीं लगता कि मुझे अपना लिखने की ज़रूरत है, वहाँ कुछ मानक होना चाहिए। धन्यवाद!


15
बस आपको ठीक-ठाक लोक अद्यतन करना था जो RegExp.escapeवर्तमान में काम कर रहा है और जो कोई भी सोचता है कि उनके पास मूल्यवान इनपुट है, योगदान करने के लिए बहुत स्वागत है। कोर-जेएस और अन्य पॉलीफिल इसे पेश करते हैं।
बेंजामिन ग्रुएनबाम

5
इस उत्तर के हालिया अपडेट के अनुसार इस प्रस्ताव को अस्वीकार कर दिया गया था: इस मुद्दे को देखें
कोशिश-कैच-अंततः

जवाबों:


573

ऊपर जुड़ा फ़ंक्शन अपर्याप्त है। यह भागने ( ^या $स्ट्रिंग के प्रारंभ और अंत) में विफल रहता है , या -, जो वर्ण समूह में श्रेणियों के लिए उपयोग किया जाता है।

इस फ़ंक्शन का उपयोग करें:

function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

हालांकि यह पहली नज़र में अनावश्यक लग सकता है, बचना -(साथ ही साथ ^) फंक्शन से बचने के लिए फंक्शन को कैरेक्टर क्लास के साथ-साथ रेगेक्स के बॉडी में डालने के लिए उपयुक्त बनाता है।

एस्केपिंग /फ़ंक्शन को जेएस रेगेक्स शाब्दिक रूप से बाद के निष्कासन के लिए उपयोग किए जाने वाले भागने के लिए उपयुक्त बनाता है।

के रूप में उनमें से किसी से बचने के लिए कोई नकारात्मक पहलू है यह व्यापक उपयोग के मामलों को कवर करने के लिए भागने के लिए समझ में आता है।

और हां, यह निराशाजनक है कि यह मानक जावास्क्रिप्ट का हिस्सा नहीं है।


16
वास्तव में, हम /सभी को बचने की जरूरत नहीं है
कांटा

28
@Paul: पर्ल quotemeta( \Q), पायथन re.escape, पीएचपी preg_quote, रूबी Regexp.quote...
बॉब

13
यदि आप इस फ़ंक्शन को एक लूप में उपयोग करने जा रहे हैं, तो शायद यह सबसे अच्छा है RegExp ऑब्जेक्ट को यह स्वयं चर है var e = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;और फिर आपका फ़ंक्शन return s.replace(e, '\\$&');इस तरह से है कि आप केवल एक बार RegExp को त्वरित कर दें।
स्टाइलफेल

15
अंतर्निहित वस्तुओं को बढ़ाने के खिलाफ मानक तर्क यहां लागू होते हैं, नहीं? यदि ECMAScript का भावी संस्करण, RegExp.escapeजिसका कार्यान्वयन आपके से अलग है, तो क्या होगा? क्या इस फ़ंक्शन के लिए कुछ भी संलग्न न होना बेहतर होगा?
मार्क एमी

15
bobince परवाह की राय के लिए परवाह नहीं है
bobince

114

लॉश का उपयोग करने वाले किसी के लिए, चूंकि v3.0.0 a _.escapeRegExp फ़ंक्शन अंतर्निहित है:

_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'

और, इस घटना में कि आपको पूर्ण लॉकेट लाइब्रेरी की आवश्यकता नहीं है, आपको बस उस फ़ंक्शन की आवश्यकता हो सकती है !


6
वहाँ भी सिर्फ इस का एक npm पैकेज है! npmjs.com/package/lodash.escaperegexp
टेड पेन्निंग्स

1
यह कोड के भार को आयात करता है जो वास्तव में इस तरह की सरल चीज के लिए होने की आवश्यकता नहीं है। बॉबिन के उत्तर का उपयोग करें ... मेरे और उसके इतने कम बाइट्स के लिए काम करता है जो लताड़ संस्करण की तुलना में लोड होता है!
रोब इवान्स

6
@RobEvans साथ मेरा उत्तर शुरू होता है "किसी के लिए lodash का उपयोग कर" , और मैं भी है कि आप की आवश्यकता हो सकती उल्लेख केवलescapeRegExp कार्य करते हैं।
gustavohenke

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

2
@ कामडोब मैं आपके द्वारा उल्लिखित उस \ x3 को नहीं देख सकता: मेरे बच गए तार अच्छे दिख रहे हैं, बस मैं जो उम्मीद करता हूं
फेडेरिको फिशोर

43

यहां अधिकांश अभिव्यक्तियाँ एकल विशिष्ट उपयोग मामलों को हल करती हैं।

यह ठीक है, लेकिन मैं "हमेशा काम करता हूं" दृष्टिकोण पसंद करता हूं।

function regExpEscape(literal_string) {
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}

यह नियमित अभिव्यक्ति में निम्नलिखित में से किसी भी उपयोग के लिए शाब्दिक स्ट्रिंग "पूरी तरह से बच जाएगा":

  • एक नियमित अभिव्यक्ति में सम्मिलन। उदाहरण के लिएnew RegExp(regExpEscape(str))
  • चरित्र वर्ग में सम्मिलन। उदाहरण के लिएnew RegExp('[' + regExpEscape(str) + ']')
  • पूर्णांक गणना विनिर्देशक में सम्मिलन। उदाहरण के लिएnew RegExp('x{1,' + regExpEscape(str) + '}')
  • गैर-जावास्क्रिप्ट नियमित अभिव्यक्ति इंजन में निष्पादन।

कवर किए गए विशेष वर्ण:

  • -: एक चरित्र वर्ग में एक चरित्र रेंज बनाता है।
  • [/ ]: एक चरित्र वर्ग को शुरू / समाप्त करता है।
  • {/ }: एक संख्यात्मक विनिर्देश को शुरू / समाप्त करता है।
  • (/ ): एक समूह को शुरू / समाप्त करता है।
  • */ +/ ?: पुनरावृत्ति प्रकार निर्दिष्ट करता है।
  • .: किसी भी पात्र से मेल खाता है।
  • \: पात्रों से बचता है, और संस्थाओं को शुरू करता है।
  • ^: मिलान क्षेत्र की शुरुआत निर्दिष्ट करता है, और एक चरित्र वर्ग में मिलान की उपेक्षा करता है।
  • $: मिलान क्षेत्र का अंत निर्दिष्ट करता है।
  • |: विकल्प निर्दिष्ट करता है।
  • #: नि: शुल्क रिक्ति मोड में टिप्पणी निर्दिष्ट करता है।
  • \s: मुक्त रिक्ति मोड में नजरअंदाज कर दिया।
  • ,: संख्यात्मक विनिर्देश में मूल्यों को अलग करता है।
  • /: अभिव्यक्ति शुरू या समाप्त करता है।
  • :: विशेष समूह प्रकारों को पूरा करता है, और पर्ल शैली के चरित्र वर्गों का हिस्सा है।
  • !: शून्य-चौड़ाई वाला समूह।
  • </ =: शून्य-चौड़ाई समूह विनिर्देशों का हिस्सा।

टिप्पणियाँ:

  • /नियमित अभिव्यक्ति के किसी भी स्वाद में कड़ाई से आवश्यक नहीं है। हालांकि, यह किसी को (कंपकंपी) मामले में बचाता है eval("/" + pattern + "/");
  • , यह सुनिश्चित करता है कि यदि स्ट्रिंग को संख्यात्मक विनिर्देशक में पूर्णांक माना जाता है, तो यह चुपचाप गलत संकलन के बजाय एक RegExp संकलन त्रुटि का कारण होगा।
  • #, और \sजावास्क्रिप्ट में भागने की जरूरत नहीं है, लेकिन कई अन्य स्वादों में करें। यदि बाद में किसी अन्य कार्यक्रम में नियमित अभिव्यक्ति दी जाएगी, तो वे यहां भाग जाते हैं।

यदि आपको जावास्क्रिप्ट रेगेक्स इंजन क्षमताओं के लिए संभावित परिवर्धन के खिलाफ नियमित अभिव्यक्ति को भविष्य में प्रूफ करने की आवश्यकता है, तो मैं और अधिकanan का उपयोग करने की सलाह देता हूं:

function regExpEscapeFuture(literal_string) {
    return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}

यह फ़ंक्शन हर वर्ण से बच जाता है, सिवाय इसके कि स्पष्ट रूप से गारंटीकृत न हो भविष्य के नियमित अभिव्यक्ति जायके में वाक्यविन्यास के लिए उपयोग किया जाए।


वास्तव में स्वच्छता-उत्सुक के लिए, इस किनारे के मामले पर विचार करें:

var s = '';
new RegExp('(choice1|choice2|' + regExpEscape(s) + ')');

यह जावास्क्रिप्ट में ठीक संकलित करना चाहिए , लेकिन कुछ अन्य स्वादों में नहीं होगा। यदि किसी अन्य स्वाद को पास करने का इरादा है, तो अशक्त मामले को s === ''स्वतंत्र रूप से जांचना चाहिए, जैसे:

var s = '';
new RegExp('(choice1|choice2' + (s ? '|' + regExpEscape(s) : '') + ')');

1
/में भाग निकले जाने की जरूरत नहीं है [...]चरित्र वर्ग।
डैन डस्केलस्क्यू

1
इनमें से अधिकांश को भागने की जरूरत नहीं है। "एक चरित्र वर्ग में एक चरित्र रेंज बनाता है" - आप स्ट्रिंग के अंदर एक चरित्र वर्ग में कभी नहीं होते हैं। "मुक्त रिक्ति मोड में टिप्पणी निर्दिष्ट करता है, मुक्त रिक्ति मोड में नजरअंदाज" - जावास्क्रिप्ट में समर्थित नहीं है। "संख्यात्मक विनिर्देश में मूल्य अलग करता है" - आप स्ट्रिंग के अंदर संख्यात्मक डेटा विनिर्देश में कभी नहीं होते हैं। इसके अलावा, आप नामांतरण विनिर्देश के अंदर मनमाना पाठ नहीं लिख सकते हैं। "अभिव्यक्ति शुरू या समाप्त होती है" - भागने की कोई आवश्यकता नहीं है। एवल एक मामला नहीं है, क्योंकि इसमें बहुत अधिक भागने की आवश्यकता होगी। [अगली टिप्पणी में जारी रखा जाएगा]
क्वर्टी २२'१

"विशेष समूह प्रकारों को पूरा करता है, और पर्ल-स्टाइल चरित्र वर्गों का हिस्सा" - जावास्क्रिप्ट में उपलब्ध नहीं लगता है। "शून्य-चौड़ाई समूह को नकारात्मक करता है, शून्य-चौड़ाई समूह विनिर्देशों का भाग" - आपके पास कभी भी स्ट्रिंग के अंदर समूह नहीं होते हैं।
क्वाटर्ली

@Qwertiy इन अतिरिक्त पलायन का कारण किनारे के मामलों को खत्म करना है जो कुछ उपयोग मामलों में समस्याएं पैदा कर सकते हैं। उदाहरण के लिए, इस फ़ंक्शन का उपयोगकर्ता किसी समूह के भाग के रूप में बची हुई रेगेक्स स्ट्रिंग को किसी अन्य समूह में सम्मिलित करना चाह सकता है, या जावास्क्रिप्ट के अलावा किसी अन्य भाषा में उपयोग के लिए भी। फ़ंक्शन "मैं कभी चरित्र वर्ग का हिस्सा नहीं होगा" जैसी धारणाएं नहीं बनाता, क्योंकि यह सामान्य होने का मतलब है । अधिक YAGNI दृष्टिकोण के लिए, यहां किसी भी अन्य उत्तर को देखें।
Pi Marillion

बहुत अच्छा। क्यों _ हालांकि बच नहीं गया है? क्या यह सुनिश्चित करता है कि शायद बाद में रेगेक्स सिंटैक्स नहीं बनेगा?
मैडप्रॉप्स

30

मोज़िला डेवलपर नेटवर्क की गाइड टू रेगुलर एक्सप्रेशंस इस से बच निकलने का कार्य प्रदान करती है:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

@DanDascalescu तुम सही हो। एमडीएन पृष्ठ अपडेट किया गया है और =अब इसमें शामिल नहीं है।
शांत दिन

21

JQueryUI के स्वत: पूर्ण विजेट (संस्करण 1.9.1) में वे थोड़ा अलग रेगेक्स (लाइन 6753) का उपयोग करते हैं, यहाँ @bobince दृष्टिकोण के साथ संयुक्त नियमित अभिव्यक्ति है।

RegExp.escape = function( value ) {
     return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}

4
एकमात्र अंतर यह है कि वे बच जाते हैं ,(जो कि एक मेटाचैकर नहीं है), #और व्हाट्सएप जो केवल फ्री-स्पेसिंग मोड (जो जावास्क्रिप्ट द्वारा समर्थित नहीं है) में मायने रखता है। हालांकि, वे इसे आगे की स्लैश से बचने के लिए नहीं करते हैं।
मार्टिन एंडर

18
यदि आप स्थानीय रूप से कोड पेस्ट करने के बजाय jquery UI के कार्यान्वयन का पुन: उपयोग करना चाहते हैं, तो साथ जाएं $.ui.autocomplete.escapeRegex(myString)
स्कॉट स्टैफ़ोर्ड

2
लताश यह भी है, _। एस्केपरेज एक्सपी और npmjs.com/package/lodash.escaperegexp
टेड पेन्निंग्स

v1.12 वही, ठीक है!
पीटर क्रूस

13

हर गैर-अल्फ़ान्यूमेरिक चरित्र से बचने से कुछ भी नहीं रोका जाना चाहिए:

usersString.replace(/(?=\W)/g, '\\');

जब आप कुछ हद तक पठनीयता खो देते हैं, re.toString()लेकिन आप सादगी (और सुरक्षा) का एक बड़ा हिस्सा जीत जाते हैं।

ECMA-262 के अनुसार, एक हाथ पर, नियमित अभिव्यक्ति "सिंटेक्स केरेक्टर्स" हमेशा गैर अक्षरांकीय ऐसी है कि परिणाम सुरक्षित है, और विशेष भागने दृश्यों (कर रहे हैं, \d, \w, \n) हमेशा अक्षरांकीय हैं ऐसी है कि कोई झूठी नियंत्रण पलायन का उत्पादन किया जाएगा ।


सरल और प्रभावी। मुझे स्वीकृत उत्तर की तुलना में यह बहुत अच्छा लगता है। पुराने ब्राउज़रों के लिए (वास्तव में) .replace(/[^\w]/g, '\\$&')उसी तरह से काम करेगा।
टॉमस लैंगकास

6
यह यूनिकोड मोड में विफल रहता है। उदाहरण के लिए, new RegExp('🍎'.replace(/(?=\W)/g, '\\'), 'u')अपवाद को फेंकता है क्योंकि \Wसरोगेट जोड़ी के प्रत्येक कोड यूनिट से अलग-अलग मेल खाता है, जिसके परिणामस्वरूप अमान्य एस्केप कोड हैं।
एलेक्सी लेब्देव

1
विकल्प:.replace(/\W/g, "\\$&");
मिगुएल पाइन्टो

@AlexeyLebedev Hes का उत्तर यूनिकोड मोड को संभालने के लिए तय किया गया है? या कहीं और एक समाधान है जो इस सरलता को बनाए रखते हुए करता है?
जॉनी क्यों

11

वहाँ कम से RegExp.escape के लिए एक ES7 प्रस्ताव है https://github.com/benjamingr/RexExp.escape/ , पर एक polyfill उपलब्ध साथ https://github.com/ljharb/regexp.escape


9
ऐसा लगता है कि यह ES7 में नहीं बना था । यह भी लगता है कि इसे टेम्प्लेट टैग की तलाश के पक्ष में खारिज कर दिया गया था ।
जॉन

6

यह एक छोटा संस्करण है।

RegExp.escape = function(s) {
    return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}

इस के गैर मेटा अक्षर शामिल हैं %, &, ', और ,, लेकिन जावास्क्रिप्ट RegExp विनिर्देश इस अनुमति देता है।


2
मैं इस "छोटे" संस्करण का उपयोग नहीं करूंगा, क्योंकि वर्ण श्रेणियां वर्णों की सूची को छिपाती हैं, जिससे पहली नज़र में शुद्धता को सत्यापित करना कठिन हो जाता है।
न्हाथ्ठ

@nhahtdh मैं शायद या तो नहीं होगा, लेकिन यह जानकारी के लिए यहां पोस्ट किया गया है।
kzh

@kzh: "सूचना के लिए" पोस्ट करना समझने के लिए पोस्ट करने से कम मदद करता है। क्या आप इस बात से सहमत नहीं होंगे कि मेरा उत्तर स्पष्ट है?
डैन डस्केल्सस्कु

कम से कम, .याद किया जाता है। और ()। या नहीं? [-^अजीब है। मुझे याद नहीं है कि क्या है।
क्वाटर्ली

वे निर्दिष्ट सीमा में हैं।
kzh


3

केवल भागने वाले पात्रों के बजाय जो आपकी नियमित अभिव्यक्ति में मुद्दों का कारण बनेंगे (जैसे: एक ब्लैकलिस्ट), इसके बजाय एक श्वेतसूची का उपयोग करने पर विचार क्यों न करें। इस तरह से प्रत्येक वर्ण को दागी माना जाता है जब तक कि वह मेल न खाए।

इस उदाहरण के लिए, निम्नलिखित अभिव्यक्ति मानें:

RegExp.escape('be || ! be');

यह श्वेतसूची पत्र, संख्या और स्थान:

RegExp.escape = function (string) {
    return string.replace(/([^\w\d\s])/gi, '\\$1');
}

यह दिखाता है:

"be \|\| \! be"

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


यह @ filip के उत्तर से अलग है? stackoverflow.com/a/40562456/209942
जॉनी क्यों


1

अन्य उत्तरों में कार्य पूरे नियमित अभिव्यक्तियों से बचने के लिए ओवरकिल हैं (वे नियमित अभिव्यक्तियों के हिस्सों से बचने के लिए उपयोगी हो सकते हैं जिन्हें बाद में बड़े रेगेक्स में बदल दिया जाएगा)।

आप एक पूरे regexp (भागने हैं और इसके साथ किया जाता है, अक्षरों से परे है कि या तो स्टैंडअलोन हैं हवाले से ., ?, +, *, ^, $, |, \) या कुछ और शुरू ( (, [, {) आप सभी की जरूरत है:

String.prototype.regexEscape = function regexEscape() {
  return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};

और हाँ, यह निराशाजनक है कि जावास्क्रिप्ट में इस बिल्ट-इन की तरह कोई फ़ंक्शन नहीं है।


मान लें कि आप उपयोगकर्ता इनपुट से बच गए हैं (text)nextऔर इसे (?:+ इनपुट + में डालें )। आपका तरीका परिणामी स्ट्रिंग देगा (?:\(text)next)जो संकलन में विफल रहता है। ध्यान दें कि यह काफी उचित प्रविष्टि है, कुछ पागल नहीं जैसे re\+ इनपुट + re(इस मामले में, प्रोग्रामर को कुछ बेवकूफ करने के लिए दोषी ठहराया जा सकता है)
nhahtdh

1
@ न्हात्थ: मेरे जवाब में विशेष रूप से पूरे नियमित भावों से बचने और उनके साथ "किए जाने" का उल्लेख है, न कि पुर्जों के हिस्सों (या भविष्य के हिस्सों) का। कृपया पूर्ववत करें?
डैन डस्केल्सस्कु

यह शायद ही कभी मामला है कि आप पूरी अभिव्यक्ति से बचेंगे - स्ट्रिंग ऑपरेशन हैं, जो कि रेगेक्स की तुलना में बहुत तेज़ हैं यदि आप शाब्दिक स्ट्रिंग के साथ काम करना चाहते हैं।
nhahtdh

यह उल्लेख नहीं कर रहा है कि यह गलत है - \बच जाना चाहिए, क्योंकि आपका रेगेक्स \wबरकरार रहेगा । इसके अलावा, जावास्क्रिप्ट अनुगामी की अनुमति नहीं देता है ), कम से कम यही है जो फ़ायरफ़ॉक्स के लिए त्रुटि फेंकता है।
न्हात्थ

1
कृपया समापन के बारे में भाग को संबोधित करें)
nhahtdh

1

एक और (अधिक सुरक्षित) दृष्टिकोण सभी पात्रों से बचने के लिए है (और कुछ विशेष नहीं जिन्हें हम वर्तमान में जानते हैं) यूनिकोड एस्केप प्रारूप का उपयोग कर रहे हैं \u{code}:

function escapeRegExp(text) {
    return Array.from(text)
           .map(char => `\\u{${char.charCodeAt(0).toString(16)}}`)
           .join('');
}

console.log(escapeRegExp('a.b')); // '\u{61}\u{2e}\u{62}'

कृपया ध्यान दें कि uइस विधि को काम करने के लिए आपको ध्वज को पास करने की आवश्यकता है :

var expression = new RegExp(escapeRegExp(usersString), 'u');

1

कभी केवल और कभी 12 मेटा चरित्र
होंगे जिन्हें एक शाब्दिक माना जाने से बचने की आवश्यकता है ।

कोई फर्क नहीं पड़ता कि बच गए स्ट्रिंग के साथ क्या किया जाता है, एक संतुलित
रेगेक्स आवरण में डाला जाता है , जोड़ा जाता है, कोई फर्क नहीं पड़ता।

इसका उपयोग करके एक स्ट्रिंग बदलें

var escaped_string = oldstring.replace( /[\\^$.|?*+()[{]/g, '\\$&' );

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