आप सीड में कई पुन: उपयोग के लिए एक जटिल रेगेक्स कैसे बचा सकते हैं?


12

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

शायद कुछ ऐसा जो दिखता है?

sed ' complicated_regex=/^(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+$/
s/complicated_regex:complicated_regex/simple-output/
' my_file

अपडेट: एक उत्तर ने बैश वैरिएबल का उपयोग करने का समाधान प्रस्तुत किया है। यह काम नहीं करता है। एक को देखते हुए test.txt

#test.txt
foo bar
bar foo

और स्क्रिप्ट

#!/bin/bash

VALUE='foo \([a-z]\+\)'

sed 's/"${VALUE}"/foo happy \1/' test.txt

यह उत्पादन का उत्पादन करना चाहिए

foo happy bar
bar foo

लेकिन इसके बजाय मुझे त्रुटि मिलती है

sed: -e expression #1, char 24: invalid reference \1 on `s' command's RHS

यदि आप पर्ल का उपयोग करते हैं, तो आप अभिव्यक्ति के पिछले हिस्सों को अभिव्यक्ति के भीतर संदर्भित कर सकते हैं:perl -pe 's/^(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+:\1$/simple_output/' my_file
ग्लेन जैकमैन

1
जब आपको सीड के लिए कुछ जटिल लगता है, तो अज़ या पर्ल के लिए जाने में संकोच न करें।
गिल्स एसओ- बुराई को रोकना '

2
@ नीति: आपका उदाहरण ठीक काम करता है, अगर आपको इसका वाक्यविन्यास सही लगता है। आपके पास "एकल-उद्धरण" अभी भी 'सिंगल-कोट्स' में संलग्न है जो इसे आपके द्वारा अपेक्षित शेल विस्तार से छुपाता है ... यह होना चाहिएsed 's/'"${VALUE}"'/foo happy \1/' test.txt
पीटर.ओ.

जवाबों:


7

आप शेल चरों का उपयोग कर सकते हैं:

complicated_regex='(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+'
sed s/^"$complicated_regex":"$complicated_regex"\$/'simple-output'/ my_file

मुझे इस बात पर यकीन नहीं है कि आपका क्या मतलब है $i, लेकिन आपको इसे एकल उद्धरण के बाहर रखने की आवश्यकता हो सकती है:

complicated_regex='(([a-f0-9]{32})+([a-zA-Z0-9=]{{'"$i"'}})?)+'

बेशक यह केवल तभी काम करता है जब sedकमांड शेल से मंगाई जाती है, लेकिन लगभग सभी प्रोग्रामिंग भाषाओं के साथ एक समान समाधान है। (और मुझे नहीं लगता कि इसके भीतर चर का उपयोग करना संभव है sed।)
स्टीफन जिमेनेज़

मानव संसाधन विकास मंत्री। यह कोशिश करते हुए, बैकरेफ्रेंस टूटी हुई दिखाई देती हैं। s/$complicated_regex/\1/यह कहते हुए एक त्रुटि देता है कि अमान्य संदर्भ है।
कोरी क्लेन

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

आपको एंकर को वैरिएबल से हटाना होगा और उन्हें सीड स्क्रिप्ट में डालना होगा:sed "s/^${complicated_regex}:${complicated_regex}\$/simple-output/" my_file
ग्लेन जैकमैन

ओह! हां, मैं यह जांचना भूल गया था कि मुझे एक वैध रेगेक्स कॉन्फैक्शन दिया गया था :-)
स्टीफन जिमेनेज़

0

शेल वैरिएबल वैल्यू में ड्रॉप करने का सबसे आसान तरीका है sedऔर इस बात की चिंता न करें कि आपकी बैकस्लैश-एस्केपिंग को आपकी sedस्क्रिप्ट के बाकी हिस्सों के लिए कैसे बदलना होगा , यह है कि वेरिएबल को छोड़कर सभी चीजों को सिंगल कोट्स में स्टफ किया जाए , और उसे डबल कोट्स में रखा जाए।

निम्नलिखित सभी कोड उदाहरण मानते हैं: VALUE='foo \([a-z]\+\)'

निम्न टूटे कोड विफल रहता है क्योंकि चर VALUEका विस्तार नहीं किया गया है:

sed 's/"${VALUE}"/foo happy \1/' test.txt

निम्न टूटा हुआ कोड विफल \1हो जाता है क्योंकि बैकस्लैश शेल द्वारा खाया जाता है (क्योंकि यह एकल उद्धरणों के बजाय दोहरे उद्धरणों में है) इससे sedपहले कि आप इसे देखें:

sed "s/${VALUE}/foo happy \1/" test.txt

निम्नलिखित कोड उम्मीद के मुताबिक काम करता है:

sed 's/'"${VALUE}"'/foo happy \1/' test.txt

निम्न कोड भी काम करता है:

sed "s/${VALUE}/foo happy \\1/" test.txt

तो निम्न कार्य करता है:

sed s/"${VALUE}"/foo\ happy\ \\1/ test.txt

लेकिन जटिल क्यों? एक sedस्क्रिप्ट के आसपास के एकल उद्धरण सब कुछ बहुत स्पष्ट करते हैं, विशेष रूप से आपके कोड को पढ़ने वाले गैर-शेल-स्क्रिप्टिंग-गुरुओं के लिए। मेरा पसंदीदा तरीका है, फिर से, एकल उद्धरणों को केवल दोहरे विस्तार से छोड़ने के लिए, परिवर्तनीय विस्तार के लिए और एकल उद्धरणों पर सही वापस कूदने के लिए:

sed 's/'"${VALUE}"'/foo happy \1/' test.txt
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.