कैसे एक चर पारित करने के लिए स्लैश युक्त


100

आप एक पैटर्न के रूप में स्लैश वाले चर को कैसे पास करते हैं sed?

उदाहरण के लिए, यदि मेरे पास निम्नलिखित चर है:

var="/Users/Documents/name/file"

मैं इसे इस sedरूप में पास करना चाहता हूं :

sed "s/$var/replace/g" "$file"

हालाँकि मुझे त्रुटियाँ मिलती हैं। मैं इस मुद्दे को कैसे दरकिनार कर सकता हूं?

जवाबों:


193

जैसा sedकि आप किसी भी सीमांकक ( नियंत्रण वर्णों सहित ) का उपयोग करने की अनुमति देता है एक वैकल्पिक रेगेक्स सीमांकक का उपयोग करें :

sed "s~$var~replace~g" $file

2
काम नहीं करता है। मैं sed -i "s ~ blah ~ $ var ~ g फ़ाइल" आज़माता हूं और प्राप्त करता हूं: "sed -e अभिव्यक्ति # 1, char 70: unterminated` s 'कमांड "। मैंने पुष्टि की है कि अपराधी $ वर में एक स्लैश है। इस समाधान के वेरिएंट सभी जगह हैं और उनमें से कोई भी काम नहीं करता है। क्या हाल ही में अपडेट किया गया था? मैं Ubuntu 14.04.4 LTS पर v4.2.2 पर हूं।
पॉल Ericson

यही कारण है कि पर निर्भर करता है क्या का मूल्य है$var
anubhava

1
के साथ काम नहीं करता है ~ as @PaulEricson मनाया, लेकिन अभी भी साथ काम करता है |
केनी हो

1
अंतिम "~" (जी के बाद) की जरूरत नहीं लगती है, कम से कम AWS अमेज़ॅन लिनक्स (CentOS आधारित) के लिए
Saúl Martínez Vidals

1
आपने मेरा दिन बचाया
user7131571

61

शुद्ध बैश उत्तर: पैरामीटर विस्तार का उपयोग चर में किसी भी स्लैश से बचने के लिए करें:

var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file

1
यह एक अच्छा तरीका है, क्योंकि आप हमेशा नहीं जानते हैं कि चर में कौन से वर्ण हैं। तो अगर आप एक संदेह है तो आप हमेशा सीमांकक से बच सकते हैं। उदाहरण के लिए: sed "s: $ {var //: / \\:}: प्रतिस्थापित करें: g" $ फ़ाइल
स्टीफन एल

सुंदर। कुछ नामकरण लिपियों की बहुत क्लीनर बनाया है।
क्लाउड

आज कुछ सुंदर सीखा, धन्यवाद। स्वीकृत उत्तर होना चाहिए।
स्टीव केहलेट

6
यहां इस्तेमाल किए जा रहे पैटर्न पर कुछ स्पष्टता ${parameter/pattern/string}:। तो, इस मामले में, पैरामीटर है var, पैटर्न है /\/, और स्ट्रिंग है \\/। पैटर्न के सभी उदाहरणों को बदल दिया जाता है क्योंकि पैटर्न ए से शुरू होता है /
जोश

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

32

इसे करने का एक और तरीका है, हालांकि शुभ के जवाब की तुलना में बदसूरत है, varएक और प्रयोग करने में सभी पीछे हटने से बच जाता है sed:

var=$(echo "$var" | sed 's/\//\\\//g')

फिर, यह काम करेगा:

sed "s/$var/replace/g" $file

12

/सीम में सीमांकक के रूप में उपयोग करने पर चर में स्लैश के साथ संघर्ष होगा जब प्रतिस्थापित किया जाएगा और परिणामस्वरूप आपको एक त्रुटि मिलेगी। इसे दरकिनार करने का एक तरीका यह है कि एक और सीमांकक का उपयोग किया जाए जो उस चर में मौजूद किसी भी वर्ण से अद्वितीय हो।

var="/Users/Documents/name/file"

आप ऑक्टोथोरपे चरित्र का उपयोग कर सकते हैं जो इस अवसर के अनुकूल है (या कोई अन्य वर्ण जो /उपयोग में आसानी के लिए नहीं है)

sed "s#$var#replace#g" 

या

sed 's#$'$var'#replace#g'

यह उपयुक्त है जब चर में रिक्त स्थान नहीं होते हैं

या

sed 's#$"'$var'"#replace#g'

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


काम नहीं करता है। मैं sed -i "s ~ blah ~ $ var ~ g फ़ाइल" आज़माता हूं और प्राप्त करता हूं: "sed -e अभिव्यक्ति # 1, char 70: unterminated` s 'कमांड "। मैंने पुष्टि की है कि अपराधी $ वर में एक स्लैश है। इस समाधान के वेरिएंट सभी जगह हैं और उनमें से कोई भी काम नहीं करता है। क्या हाल ही में अपडेट किया गया था? मैं Ubuntu 14.04.4 LTS पर v4.2.2 पर हूं।
पॉल Ericson

@PaulEricson मैं अपने लिए उपलब्ध किसी भी उबंटू पर इसे वापस करने में असमर्थ हूं। यदि आपका $varसम्‍मिलित है ~, तो आपको स्‍पष्‍ट रूप से एक अलग परिसीमन चुनना होगा। "असंबद्ध" त्रुटि लगता है जैसे आपके पास $varएक नई पंक्ति है; आप इसे मान सकते हैं कि बैकस्लैश-हर मूल्य में हर नई लाइन से बच सकता है, लेकिन मुझे नहीं लगता कि यह पूरी तरह से पोर्टेबल है। यह मूल्य में स्लैश की समस्या से असंबद्ध और बड़ा है।
ट्रिपल डे

@PaulEricson ओह और आपका उद्धरण गलत है, आपके पास उद्धरणों के अंदर फ़ाइल नाम नहीं होना चाहिए। sed -i "s~blah~$var~g" fileकेवल वास्तविक sedस्क्रिप्ट के चारों ओर उद्धरण के साथ ।
ट्रिपलए

5

यह एक पुराना प्रश्न है, लेकिन यहां कोई भी उत्तर s/from/to/बहुत विस्तार से अन्य कार्यों पर चर्चा नहीं करता है।

sedकथन का सामान्य रूप है

*address* *action*

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

sed '1,4d' file

4 के माध्यम से लाइनों 1 नष्ट करेगा ( पता लाइन नंबर रेंज है 1,4और कार्रवाई है dहटाएँ आदेश); तथा

sed '/ick/,$s/foo/bar/' file

की पहली आवृत्ति का स्थान ले लेगा fooसाथ barregex पर पहला मैच के बीच किसी भी लाइन पर ickऔर फ़ाइल के अंत ( पता रेंज है /ick/,$और कार्रवाई है sस्थानापन्न आदेश s/foo/bar/)।

इस संदर्भ में, यदि ickआप एक चर से आते हैं , तो आप कर सकते हैं

sed "/$variable/,\$s/foo/bar/"

(सिंगल के बजाय डबल कोट्स के उपयोग पर ध्यान दें, ताकि शेल वैरिएबल को इंटरपोल कर सके, और शाब्दिक डॉलर के चिन्ह को डबल कोट्स के अंदर कोट करने की आवश्यकता हो) लेकिन अगर वेरिएबल में स्लैश है, तो आपको सिंटैक्स त्रुटि मिलेगी। (शेल चर का विस्तार करता है, फिर परिणामी स्ट्रिंग को पास करता है sed; इसलिए sedकेवल शाब्दिक पाठ देखता है - इसमें शेल के चर की कोई अवधारणा नहीं है।)

इलाज के लिए एक अलग सीमांकक का उपयोग करना होता है (जहां स्पष्ट रूप से आपको एक वर्ण का उपयोग करने में सक्षम होना चाहिए जो चर के मूल्य में नहीं हो सकता है), लेकिन s%foo%bar%मामले के विपरीत , आपको परिसीमा से पहले एक बैकस्लैश की भी आवश्यकता है यदि आप एक अलग का उपयोग करना चाहते हैं डिफ़ॉल्ट की तुलना में सीमांकक /:

sed "\\%$variable%,\$s/foo/bar/" file

(एकल उद्धरण के अंदर, एक एकल बैकस्लैश स्पष्ट रूप से पर्याप्त होगा); या आप अलग से मूल्य में हर स्लैश से बच सकते हैं। यह विशेष वाक्य विन्यास केवल बैश है:

sed "/${variable//\//\\/}/,\$s/foo/bar/" file

या यदि आप एक अलग शेल का उपयोग करते हैं, तो प्रयास करें

escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file

स्पष्टता के लिए, यदि $variableस्ट्रिंग समाहित है 1/2तो उपरोक्त आदेशों के बराबर होगा

sed '\%1/2%,$s/foo/bar/' file

पहले मामले में, और

sed '/1\/2/,$s/foo/bar/' file

क्षण में।


4

पर्ल का उपयोग करें, जहां चर प्रथम श्रेणी के नागरिक हैं, न कि केवल मैक्रोज़ का विस्तार करने के लिए:

var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
  • -p प्रोसेसिंग द्वारा इनपुट लाइन को पढ़ता है और प्रोसेसिंग के बाद लाइन को प्रिंट करता है
  • \Qनिम्नलिखित स्ट्रिंग में सभी मेटाचैकर को उद्धृत करता है (यहां प्रस्तुत मूल्य के लिए आवश्यक नहीं है, लेकिन आवश्यक है यदि मूल्य समाहित है [या कुछ अन्य मूल्य नियमित व्यय के लिए विशेष हैं)

स्टाॅक एक्सचेंज के पार "आम तौर पर sed अभिव्यक्ति में चर का उपयोग" के दर्जनों के लिए एकमात्र उपयोगी उत्तर। बाकी सब कुछ प्रभावी रूप से "कुछ भी है जो sed के लिए विशेष है से बच" है, जो व्यावहारिक रूप से बेकार है चर की परिवर्तनशीलता और sed की।
हीथ राफ्टी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.