कहें कि मेरे पास निम्न की तरह एक नियमित अभिव्यक्ति है, लेकिन मैंने इसे एक फ़ाइल से एक परिवर्तनीय $ regex में लोड किया है, और इसलिए डिजाइन समय पर इसकी कोई जानकारी नहीं है कि इसकी सामग्री क्या है, लेकिन रनटाइम पर मैं खोज कर सकते हैं कि यह "version1", "version2", "version3" और "version4" नाम के समूहों में शामिल हैं:पावरहेल: चर के साथ समूह नामित रेगेक्स को बदलना
"Version (?<version1>\d),(?<version2>\d),(?<version3>\d),(?<version4>\d)"
... और मुझे इन चरों है:
$version1 = "3"
$version2 = "2"
$version3 = "1"
$version4 = "0"
.. और मैं एक फ़ाइल में निम्न स्ट्रिंग में आ गया:
Version 7,7,0,0
... जो एक परिवर्तनीय $ इनपुट में संग्रहीत है, ताकि ($ इनपुट-$ $ regex) $ true का मूल्यांकन हो।
$ version1, $ version2, $ version3, $ version4 के मानों के साथ स्ट्रिंग $ इनपुट में नामित समूहों को $ regex से कैसे बदल सकता है यदि मुझे यह पता नहीं है कि वे $ regex (I केवल इतना पता है कि $ regex इन नामित समूहों को शामिल करता है)?
मुझे किसी नाम समूह को प्रतिस्थापित करने के लिए समूह नाम का उपयोग करके एक चर के मूल्य के साथ नामित समूह को बदलने के लिए वाक्यविन्यास का वर्णन करने के लिए कोई संदर्भ नहीं मिल रहा है - क्या यह भी समर्थित है?
संपादित करें: स्पष्ट करने के लिए - लक्ष्य पाठ फ़ाइल के किसी भी प्रकार जहां एक दिया फाइल में संस्करण स्ट्रिंग संस्करण क्षेत्रों के परिवर्तनशील के प्रतिस्थापन की आवश्यकता में टेम्प्लेटेड संस्करण तार को बदलने के लिए है (2, 3 हो सकता है, या सभी 4 फ़ील्ड)। उदाहरण के लिए, एक फ़ाइल में पाठ इनमें से किसी भी दिखाई दे सकता है (लेकिन इन तक सीमित नहीं है):
#define SOME_MACRO(4, 1, 0, 0)
Version "1.2.3.4"
SomeStruct vs = { 99,99,99,99 }
उपयोगकर्ता के साथ, खेतों युक्त लाइन से मिलान करने के लिए एक फ़ाइल सेट और एक रेगुलर एक्सप्रेशन निर्दिष्ट कर सकते हैं मूल विचार यह है कि अलग-अलग क्षेत्रों को नामित समूहों द्वारा पकड़ा जाएगा। उपयोगिता में अलग-अलग संस्करण फ़ील्ड मान होते हैं जिन्हें फ़ाइल में प्रतिस्थापित किया जाना चाहिए, लेकिन उस रेखा के मूल स्वरूप को संरक्षित करना है जिसमें प्रतिस्थापन होंगे, और केवल अनुरोधित फ़ील्ड को प्रतिस्थापित करें।
संपादित -2: मुझे लगता है कि मैं परिणाम मैं स्थिति और मैचों में से प्रत्येक की सीमा के आधार पर सबस्ट्रिंग गणना के साथ की जरूरत है प्राप्त कर सकते हैं, लेकिन उम्मीद थी Powershell के बदलने के आपरेशन मुझे कुछ काम को बचाने के लिए जा रहा था।
संपादित-3: तो, Ansgar के रूप में सही ढंग से और संक्षेप में नीचे का वर्णन करता है, वहाँ नहीं एक तरह से (केवल मूल इनपुट स्ट्रिंग, एक रेगुलर एक्सप्रेशन जिसके बारे में आप केवल नाम के समूहों पता उपयोग कर रहा है, और जिसके परिणामस्वरूप मैचों) नामित समूहों के कैप्चर के प्रतिस्थापन करने के लिए "-रेप्लेस" ऑपरेशन (या अन्य रेगेक्स ऑपरेशंस) का उपयोग करने के लिए, शेष मूल स्ट्रिंग को बरकरार रखते हुए। इस समस्या के लिए, अगर कोई उत्सुक है, तो मैं नीचे दिए गए समाधान का उपयोग कर समाप्त हुआ। वाईएमएमवी, अन्य समाधान संभव है। उनके प्रतिक्रिया और विकल्पों के लिए Ansgar के लिए बहुत धन्यवाद।
निम्नलिखित कोड ब्लॉक में:
- $ इनपुट पाठ की एक पंक्ति है जिस पर प्रतिस्थापन किया जाने
- $ regex है (प्रकार की [स्ट्रिंग]) एक रेगुलर एक्सप्रेशन एक फ़ाइल से पढ़ने है जिसे समर्थित नामित समूहों में से कम से कम एक को सत्यापित करने के लिए सत्यापित किया गया है
- $ regexToGroupName एक हैश तालिका है जो [regex] :: GetGroupNames द्वारा लौटाए गए सरणी के क्रम के अनुसार क्रमबद्ध समूह नामों की एक सरणी में रेगेक्स स्ट्रिंग को मैप करती है() है, जो बाएँ से सही क्रम जिसमें वे अभिव्यक्ति में प्रदर्शित से मेल खाता है
- $ groupNameToVersionNumber एक हैश तालिका एक संस्करण संख्या के लिए एक समूह का नाम नक्शे है।
$ regex के भीतर नामित समूहों पर बाधा केवल (मुझे लगता है) कि नामित समूहों के भीतर अभिव्यक्ति घोंसला नहीं जा सकती है, और इनपुट स्ट्रिंग के भीतर सबसे अधिक बार मिलना चाहिए।
# This will give us the index and extent of each substring
# that we will be replacing (the parts that we will not keep)
$matchResults = ([regex]$regex).match($input)
# This will hold substrings from $input that were not captured
# by any of the supported named groups, as well as the replacement
# version strings, properly ordered, but will omit substrings captured
# by the named groups
$lineParts = @()
$startingIndex = 0
foreach ($groupName in $regexToGroupName.$regex)
{
# Excise the substring leading up to the match for this group...
$lineParts = $lineParts + $input.Substring($startingIndex, $matchResults.groups[$groupName].Index - $startingIndex)
# Instead of the matched substring, we'll use the substitution
$lineParts = $lineParts + $groupNameToVersionNumber.$groupName
# Set the starting index of the next substring that we will keep...
$startingIndex = $matchResults.groups[$groupName].Index + $matchResults.groups[$groupName].Length
}
# Keep the end of the original string (if there's anything left)
$lineParts = $lineParts + $input.Substring($startingIndex, $input.Length - $startingIndex)
$newLine = ""
foreach ($part in $lineParts)
{
$newLine = $newLine + $part
}
$input= $newLine
सहमत हैं कि यह अच्छा होगा, लेकिन यह एक उपयोगिता के लिए है जहां उपयोगकर्ता रेगेक्स और फ़ाइल सेट निर्दिष्ट करते हैं। मुझे regex नहीं पता है, और मुझे नहीं पता कि फ़ाइल सामग्री कैसा दिखता है, इसलिए मैं मूल फ़ाइल सामग्री को दोबारा सुधार किए बिना आपके उत्तर में पहली पंक्ति का उपयोग नहीं कर सका, जो अवांछित होगा। मुझे फ़ाइल सामग्री को उसी संस्करण को छोड़ना होगा, केवल अलग-अलग संस्करण फ़ील्ड के साथ मेल खाने वाली लाइनों पर केवल सबस्ट्रिंग को बदलना होगा। – Hoobajoob
शायद आप नामित समूहों को वास्तविक अभिव्यक्ति में वास्तविक पुरानी/नई संख्याओं के साथ प्रतिस्थापित कर सकते हैं और फिर स्ट्रिंग को प्रतिस्थापित कर सकते हैं। यदि नियमित अभिव्यक्ति में नामित समूहों के अलावा अन्य अभिव्यक्तियां हैं, तो यह सही तरीके से काम नहीं करेगा। –
यह लगभग काम करता है, हालांकि मुझे पहले से पता नहीं है कि रेगेक्स में नामित समूह वास्तव में परिभाषित किए गए हैं (उदाहरण के लिए, वे \ d, \ d {2}, \ d +, एक शाब्दिक, आदि की तलाश में हो सकते हैं) । मैं नामित समूह परिभाषा पर कुछ बाधाओं को पेश कर सकता हूं और रेज़िक्स सिंटैक्स से एक या अधिक वर्णों को स्वीकार करने के लिए ऊपर दिए गए लूप में उपयोग किए गए रेगेक्स को बदल सकता हूं, साथ ही अल्फान्यूमेरिक (उदाहरण के लिए, "\\ d" को रेगेक्स में बदल दें लूप के लिए "[a-zA-Z0 -9 \\ + \। \ * \? \^\ $ \ {\} \ | \ [\]] +")। किसी भी दर पर, यह दृष्टिकोण संचालन घटाने के लिए बेहतर है। – Hoobajoob