जावास्क्रिप्ट में अपरकेस के साथ एक रेगेक्स कैप्चर समूह को बदलें


81

मैं यह जानना चाहता हूं कि जावास्क्रिप्ट में कैप्चर समूह को अपने अपरकेस से कैसे बदला जाए। यहाँ मैंने जो अभी तक कोशिश की है उसका एक सरलीकृत संस्करण है जो काम नहीं कर रहा है:

> a="foobar"
'foobar'
> a.replace( /(f)/, "$1".toUpperCase() )
'foobar'
> a.replace( /(f)/, String.prototype.toUpperCase.apply("$1") )
'foobar'

क्या आप बताएंगे कि इस कोड में क्या गलत है?


@ एरिक प्रश्न के एक घटक को नहीं हटाते हैं। मैं जानना चाहता हूं कि मेरा कोड क्यों फेल हो रहा है।
इवान कैरोल

इवान, मुझे लगा कि मैं आपके प्रश्न का सम्मान कर रहा हूं। मैंने केवल उन चीजों को हटा दिया जो अनावश्यक लगती थीं। चूँकि आपने जो कोड की कोशिश कर रहे थे, वह दे दिया और यह स्पष्ट रूप से काम नहीं कर रहा था, तब लोगों को पता था कि आपको इस बात की व्याख्या की आवश्यकता है कि आपके बिना ऐसा क्यों कहा जा सकता है (और अजीब तरह से)। बस मदद करने का प्रयास कर रहा हूं! :)
एरिक

1
इवान, यह बेहतर है? मुझे गुस्सा करने का मतलब नहीं है। यदि आप फिर से रोलबैक करते हैं तो मैं फिर से संपादित नहीं करूंगा, लेकिन क्या आप कम से कम शीर्षक और टैग संपादन जगह पर रख सकते हैं?
एरिक

तकनीकी रूप से, मैं जावास्क्रिप्ट का उपयोग बिल्कुल नहीं कर रहा हूं, मैं v8 (ECMAScript) का उपयोग कर रहा हूं। लेकिन, मुझे लगता है कि यह खोज करने वाले अधिकांश लोग जावास्क्रिप्ट की तलाश करेंगे, इसलिए मैं इसके साथ अच्छा हूं।
इवान कैरोल

1
यदि आपको लगता है कि वे संबंधित हैं तो टैग जोड़ने के लिए स्वतंत्र महसूस करें।
एरिक

जवाबों:


159

आप किसी फ़ंक्शन को पास कर सकते हैं replace

var r = a.replace(/(f)/, function(v) { return v.toUpperCase(); });

व्याख्या

a.replace( /(f)/, "$1".toUpperCase())

इस उदाहरण में आप स्ट्रिंग को प्रतिस्थापित फ़ंक्शन में पास करते हैं। चूँकि आप विशेष प्रतिस्थापित सिंटैक्स ($ N को Nth कैप्चर करते हैं ) का उपयोग कर रहे हैं, आप बस उसी मान को दे रहे हैं। toUpperCaseवास्तव में धोखा दे क्योंकि आप केवल की जगह स्ट्रिंग अपर केस बना रहे है (जो कुछ हद तक व्यर्थ है क्योंकि $और एक 1वर्ण कोई ऊपरी मामला है तो वापसी मान अभी भी हो जाएगा "$1")

a.replace( /(f)/, String.prototype.toUpperCase.apply("$1"))

मानो या न मानो इस अभिव्यक्ति के शब्दार्थ बिल्कुल समान हैं।


@ इवान कैरोल: कृपया मेरा उत्तर देखें।
काया

4
आह, मैं देख रहा हूं कि आपका क्या मतलब है, मैं "$ 1" को बढ़ा रहा हूं। वूडू का परिणाम जो प्रतिस्थापित नहीं करता है, वह स्पष्ट रूप $1से पहले कैप्चर समूह के लिए प्रतिस्थापन है ।
इवान कैरोल

@EvanCarroll के बारे में गहन व्याख्या के लिए कि आपका आरंभिक कोड काम क्यों नहीं करता है और इसे कैसे प्राप्त किया जा सकता है, नीचे मेरा उत्तर देखें।
जोशुआ पिकरी

15

मुझे पता है कि मुझे पार्टी में देर हो रही है लेकिन यहाँ एक छोटी विधि है जो आपके शुरुआती प्रयासों की तर्ज पर अधिक है।

a.replace('f', String.call.bind(a.toUpperCase));

तो आप कहां गलत हो गए और यह नया वूडू क्या है?

समस्या 1

जैसा कि पहले कहा गया था, आप String.prototype.replace () के दूसरे पैरामीटर के रूप में एक तथाकथित विधि के परिणामों को पारित करने का प्रयास कर रहे थे , जब इसके बजाय आपको किसी फ़ंक्शन का संदर्भ देना चाहिए।

समाधान 1

जिसे हल करना काफी आसान है। बस मापदंडों और कोष्ठक को हटाने से हमें फ़ंक्शन को निष्पादित करने के बजाय एक संदर्भ मिलेगा।

a.replace('f', String.prototype.toUpperCase.apply)

समस्या २

यदि आप कोड को चलाने का प्रयास करते हैं, तो आपको यह बताते हुए एक त्रुटि मिलेगी कि अपरिभाषित एक फ़ंक्शन नहीं है और इसलिए इसे नहीं बुलाया जा सकता है। इसका कारण यह है कि String.prototype.toUpperCase.apply जावास्क्रिप्ट के प्रोटोटाइप वंशानुक्रम के माध्यम से वास्तव में Function.prototyp.apply () का संदर्भ है । इसलिए हम वास्तव में जो कर रहे हैं वह इस तरह दिखता है

a.replace('f', Function.prototype.apply)

जो स्पष्ट रूप से नहीं है जो हमने इरादा किया है। कैसे इसे चलाने के लिए पता है Function.prototype.apply () पर String.prototype.toUpperCase () ?

समाधान २

Function.prototyp.bind () का उपयोग करके हम विशेष रूप से String.prototype.toUpperCase पर सेट इसके संदर्भ के साथ Function.prototyp.call की एक प्रति बना सकते हैं। अब हमारे पास निम्नलिखित हैं

a.replace('f', Function.prototype.apply.bind(String.prototype.toUpperCase))

समस्या 3

अंतिम मुद्दा यह है कि String.prototyp.replace () अपने प्रतिस्थापन फ़ंक्शन के लिए कई तर्क पारित करेगा। हालाँकि, Function.prototype.apply () एक पैरामीटर होने के लिए दूसरे पैरामीटर की अपेक्षा करता है लेकिन इसके बजाय या तो एक स्ट्रिंग या संख्या प्राप्त करता है (यह निर्भर करता है कि आप कैप्चर समूहों का उपयोग करते हैं या नहीं)। यह एक अमान्य तर्क सूची त्रुटि का कारण होगा।

समाधान 3

सौभाग्य से, हम बस Function.prototype.call () में प्रतिस्थापन कर सकते हैं (जो किसी भी प्रकार के तर्कों को स्वीकार करता है, जिनमें से किसी के पास भी फ़ंक्शन के प्रकार नहीं हैं) फ़ंक्शन .prototyp.apply () । हम अब वर्किंग कोड पर आ गए हैं!

a.replace(/f/, Function.prototype.call.bind(String.prototype.toUpperCase))

बहा बाइट्स!

कोई भी बार का एक प्रकार प्रोटोटाइप टाइप नहीं करना चाहता है । इसके बजाय हम इस तथ्य का लाभ उठाएंगे कि हमारे पास ऐसी वस्तुएँ हैं जो विरासत के माध्यम से समान विधियों का संदर्भ देती हैं। स्ट्रिंग कंस्ट्रक्टर, एक फ़ंक्शन होने के नाते, फ़ंक्शन के प्रोटोटाइप से विरासत में मिला है। इसका मतलब है कि हम के लिए String.call में स्थानापन्न कर सकते हैं Function.prototype.call (वास्तव में हम और भी बाइट्स लेकिन कम अर्थ है कि बचाने के लिए Date.call उपयोग कर सकते हैं)।

हम अपने वैरिएबल 'a' का भी लाभ उठा सकते हैं क्योंकि प्रोटोटाइप में String.prototyp.toUpperCase का संदर्भ शामिल है। हम इसे a.toUpperCase के साथ स्वैप कर सकते हैं। यह ऊपर दिए गए 3 समाधानों का संयोजन है और ये बाइट बचत के उपाय हैं कि कैसे हम इस पोस्ट के शीर्ष पर कोड प्राप्त करते हैं।


4
अधिक स्पष्ट समाधान पर स्पष्टीकरण के एक पृष्ठ की आवश्यकता के लिए कोड को इस तरह से अस्पष्ट करते हुए आपने 8 वर्णों को बचाया। मुझे यकीन नहीं हुआ कि यह जीत है।
लॉरेंस डॉल

1
बौद्धिक रूप से, यह एक महान समाधान है, जिसमें यह जावास्क्रिप्ट कार्यों के बारे में एक बात या 2 को सतहों / सिखाता है। लेकिन मैं लॉरेंस के साथ हूँ कि वास्तव में यह वास्तव में इस्तेमाल किया जा अस्पष्ट है। फिर भी मस्त।
मीटमैट

9

पुरानी पोस्ट लेकिन यह अधिक प्रतिबंधित RegEx के साथ अन्य उपयोग के मामलों के लिए @ChaosPandion उत्तर का विस्तार करने के लिए लायक है। जैसे (f)एक विशिष्ट प्रारूप के साथ समूह को कैप्चर या कैप्चर करना सुनिश्चित करें /z(f)oo/:

> a="foobazfoobar"
'foobazfoobar'
> a.replace(/z(f)oo/, function($0,$1) {return $0.replace($1, $1.toUpperCase());})
'foobazFoobar'
// Improve the RegEx so `(f)` will only get replaced when it begins with a dot or new line, etc.

मैं केवल functionएक विशिष्ट प्रारूप खोजने और संभवत: प्रारूप के भीतर एक कैप्चरिंग समूह की जगह बनाने के दो मापदंडों को उजागर करना चाहता हूं ।


धन्यवाद! पिछले पोस्टों ने इस समस्या का उत्तर दिया है कि ओपी का कोड पूरी तरह से लंघन करते समय काम क्यों नहीं करता है, जो मुझे वास्तविक बिंदु लगता है - एक मैच समूह की जगह!
शुभ अंक

मुझे लगता है कि आपको अपने प्रतिस्थापित फ़ंक्शन में कोई त्रुटि है, लेकिन इस पर मुझे जांचें। मुझे लगता है कि यह होना चाहिए return $0.replace($0, $1.toUpperCase()), जहां $0पहला तर्क है
माइक

यह स्ट्रिंग को बदलने के लिए एक सरल स्ट्रिंग थी। इसलिए F से F सही है।
CallMeLaNN

यदि आप कोष्ठक में कुछ बदलने की कोशिश कर रहे हैं तो यह वास्तव में मददगार है!
डायोड डैन

3

हम सिर्फ परिभाषा को क्यों नहीं देखते हैं ?

यदि हम लिखते हैं:

a.replace(/(f)/, x => x.toUpperCase())

हम भी कह सकते हैं:

a.replace('f','F')

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

function replacer(match, p1, p2, p3, offset, string)

यदि आप तीर फ़ंक्शन नोटेशन का उपयोग करना चाहते हैं:

a.replace(/xxx(yyy)zzz/, (match, p1) => p1.toUpperCase()

1

उपाय

a.replace(/(f)/,x=>x.toUpperCase())  

रिपुक्स का उपयोग करने के लिए सभी ग्रूप घटनाओं को प्रतिस्थापित करने के लिए /(f)/g। आपके कोड में समस्या: String.prototype.toUpperCase.apply("$1")और "$1".toUpperCase()देता है "$1"(स्वयं द्वारा कंसोल में प्रयास करें) - इसलिए यह कुछ भी नहीं बदलता है और वास्तव में आप दो बार कॉल करते हैं a.replace( /(f)/, "$1")(जो भी बदलते हैं)।


0

एक शब्दकोश (वस्तु, इस मामले में, Mapसंपत्ति, मूल्यों, और .bind()जवाब में वर्णित के रूप में ) का उपयोग कर दिया

const regex = /([A-z0-9]+)/;
const dictionary = new Map([["hello", 123]]); 
let str = "hello";
str = str.replace(regex, dictionary.get.bind(dictionary));

console.log(str);

एक जावास्क्रिप्ट सादे वस्तु का उपयोग करना और एक फ़ंक्शन के साथ परिभाषित किया गया है ताकि वस्तु का मिलान किया गया संपत्ति मूल्य, या मूल स्ट्रिंग मिल सके यदि कोई मिलान नहीं मिला है

const regex = /([A-z0-9]+)/;
const dictionary = {
  "hello": 123,
  [Symbol("dictionary")](prop) {
    return this[prop] || prop
  }
};
let str = "hello";
str = str.replace(regex, dictionary[Object.getOwnPropertySymbols(dictionary)[0]].bind(dictionary));

console.log(str);

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