Sed में पर्यावरण चर प्रतिस्थापन


202

अगर मैं इन कमांड को स्क्रिप्ट से चलाता हूं:

#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla

यह ठीक है।

लेकिन, अगर मैं चला:

#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s' 

मैंने उन ट्यूटोरियल्स में पढ़ा है कि शेल से पर्यावरण वेरिएबल्स को बदलने के लिए आपको रुकने की जरूरत है, और $varnameपार्ट को 'आउट' करें ताकि इसे सीधे सब्स्टीट्यूट नहीं किया जा सके, जो कि मैंने किया है, और जो कि तभी काम करता है जब वेरिएबल को तुरंत परिभाषित किया जाए।

$varशेल के रूप में परिभाषित किए गए परिवेश चर के रूप में मुझे पहचानने के लिए कैसे sed मिल सकता है ?


4
$ PWD में एक / होता है जो स्थानापन्न कमांड को समाप्त करता है।
फोबर्ट

@derobert: tnx समाधान में से एक इसे संबोधित करता है ...
रोमन

4
set -xशेल का उपयोग शेल को पाने से पहले प्रत्येक कमांड को इको करने के लिए किया जाता है। इससे काफी भ्रम की स्थिति साफ हो सकती है। (इसके अलावा, मैं अक्सर set -uडी- set -e
रेफ़रिंग का

मैं पर्यावरण चर को संभालने के लिए sed के लिए एक रास्ता खोजने की उम्मीद कर रहा था क्योंकि प्रक्रिया तालिका में मानों को लीक नहीं करना है, ऐसा लगता है जैसे sed इस धागे में सभी उत्तरों के अनुसार रहस्य स्थापित करने के लिए गलत उपकरण है
ThorSummoner

जवाबों:


302

आपके दो उदाहरण समान दिखते हैं, जिससे समस्याओं का निदान कठिन हो जाता है। संभावित समस्याएं:

  1. आपको दोहरे उद्धरण चिह्नों की आवश्यकता हो सकती है sed 's/xxx/'"$PWD"'/'

  2. $PWDइसमें एक स्लैश शामिल हो सकता है, जिस स्थिति में आपको एक चरित्र खोजने की आवश्यकता होती है जो एक सीमांकक के रूप में उपयोग करने के लिए निहित नहीं$PWD है।

एक बार में दोनों मुद्दों को कील करने के लिए, शायद

sed 's@xxx@'"$PWD"'@'

लेकिन, फिर मैं किस चरित्र का उपयोग कर सकता हूं यह मुझे पता है कि पथ नाम में दिखाई नहीं देगा?
रोमन

5
आपके पास कई उम्मीदवार हो सकते हैं जैसे @ #%! और अगर $ PWD उनके पास है, तो केस एक्सप्रेशन के साथ जांच करें। जैसे, @ का मामला "$ PWD" ;; *) डेलिम = "@" ;; esac; तब तक दोहराएं जब तक $ डेलिम खाली न हो जाए।
नॉर्मन राम्से

दोहरे उद्धरण चिह्नों का उपयोग करने के बजाय एक और विकल्प है। नीचे मेरा जवाब देखें।
थेल्स Ceolin

आप sed के लिए एक और सीमांकक का उपयोग कर सकते हैं। आपको उपयोग करने की आवश्यकता नहीं है / आप उपयोग कर सकते हैं, साथ ही अगर आपका पर्यावरण चर एक यूआरएल है।
गुहेल्केबेन ने

123

नॉर्मन राम्सी के जवाब के अलावा, मैं यह जोड़ना चाहूंगा कि आप पूरे स्ट्रिंग को डबल-कोट कर सकते हैं (जो कथन को अधिक पठनीय और कम त्रुटि वाला बना सकते हैं)।

इसलिए यदि आप 'फू' खोजना चाहते हैं और इसे $ BAR की सामग्री से बदलना चाहते हैं, तो आप sed कमांड को डबल-कोट्स में संलग्न कर सकते हैं।

sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"

पहले में, $ BAR सही ढंग से विस्तार नहीं करेगा जबकि दूसरे $ BAR में सही तरीके से विस्तार होगा।


4
यह दोहरे उद्धरण चिह्नों, एकल उद्धरणों आदि के साथ खिलवाड़ करने से साफ है
व्लादिस्लाव डोभालक

इस आदेश में सही ढंग से विस्तार करने के लिए पर्यावरण चर प्राप्त करने के लिए मुझे इसका उपयोग करना था: sed -i "s / 127.0.0.1 / 127.0.0.1 localhost $ HOSTNAME /" होस्ट
izikandrw

2
यह साफ है, लेकिन यह काम नहीं कर रहा है जब आप कुछ और अधिक जटिल प्रतिस्थापन, इस तरह के रूप में करना चाहते हैं "2,$s/^/$foo/"के रूप में $sएक चर के रूप में भी व्याख्या की जाती है और ऐसा नहीं होना चाहिए।
एमजेपी

59

आप प्रतिस्थापन में "/" के अलावा अन्य वर्णों का उपयोग कर सकते हैं:

sed "s#$1#$2#g" -i FILE

मेरे विशिष्ट मामले में, $ 2 एक फ़ाइल पथ sedथा , इसलिए /$ 2 की सामग्री में व्याख्या करने के कारण बाधा थी । यह वही था जो मुझे इसे पाने के लिए आवश्यक था। धन्यवाद महान टिप!
बॉयड हेम्फिल

54

एक और आसान विकल्प:

चूंकि $PWDआमतौर पर एक स्लैश होता है /, |इसके बजाय /sed स्टेटमेंट के लिए उपयोग करें :

sed -e "s|xxx|$PWD|"

4
आपने कहा "दोहरे उद्धरण चिह्नों का उपयोग करने का एक विकल्प" और फिर भी आपका उदाहरण दोहरे उद्धरण चिह्नों का उपयोग करता है?
5

मुझे लगता है कि यह बिंदु है कि यह सीधे दोहरे-उद्धरणों का उपयोग नहीं करता है $PWD...?
क्रिश्चियन

14

आपके प्रश्न को संपादित करने के साथ, मुझे आपकी समस्या दिखाई दे रही है। मान लीजिए कि वर्तमान निर्देशिका है /home/yourname ... इस मामले में, आपकी आज्ञा नीचे दी गई है:

sed 's/xxx/'$PWD'/'

तक विस्तारित किया जाएगा

sed `s/xxx//home/yourname//

जो मान्य नहीं है। यदि आप ऐसा करना चाहते हैं तो आपको अपने $ PWD में \प्रत्येक के सामने एक पात्र रखना /होगा।


लेकिन पीडब्लूडी को शेल द्वारा परिभाषित किया गया है ... अगर मैं गूंज $ पीडब्ल्यूडी को प्राप्त करता हूं तो मुझे pwd मिलता है
रोमन

1
तो, आप पर्यावरण चर से कैसे बचते हैं?
einpoklum

1
चयनित उत्तर वर्कअराउंड का वर्णन करता है ... परिसीमन के लिए स्लैश का उपयोग न करें
एडी

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

6

बुरा तरीका: परिसीमन बदलें

sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's@xxx@'"$PWD"'@'

शायद उन लोगों को अंतिम जवाब नहीं,

आप यह नहीं जान सकते कि किस चरित्र में क्या होगा $PWD, / :या @

अच्छा तरीका विशेष चरित्र की जगह है $PWD

अच्छा तरीका: सीमांकक बचो

उदाहरण के लिए: URL$ url ( : /सामग्री में है) के रूप में प्रतिस्थापित करने का प्रयास करें

x.com:80/aa/bb/aa.js

$ tmp में

<a href="URL">URL</a>

ए। /सीमांकक के रूप में उपयोग करें

echo ${url//\//\\/}
x.com:80\/aa\/bb\/aa.js

echo ${url//\//\/}
x.com:80/aa/bb/aa.js

echo "${url//\//\/}"
x.com:80\/aa\/bb\/aa.js

echo $tmp | sed "s/URL/${url//\//\\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

echo $tmp | sed "s/URL/${url//\//\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

या

ख। :सीमांकक के रूप में उपयोग (से अधिक पठनीय /)

echo ${url//:/\:}
x.com:80/aa/bb/aa.js

echo "${url//:/\:}"
x.com\:80/aa/bb/aa.js

echo $tmp | sed "s:URL:${url//:/\:}:g"
<a href="x.com:80/aa/bb/aa.js">x.com:80/aa/bb/aa.js</a>

3

दरअसल, सरलतम चीज़ (कम से कम ग्नू सेड में) सेड प्रतिस्थापन (एस) कमांड के लिए एक अलग विभाजक का उपयोग करना है। इसलिए s / पैटर्न / '$ mypath' के बजाय / s / pattern // my / path / तक विस्तारित किया जा रहा है, जो निश्चित रूप से s कमांड को भ्रमित करेगा, s! पैटर्न का उपयोग करें! '$ Mypath' जिसे s! पैटर्न में विस्तारित किया जाएगा! / मेरे / पथ मैंने धमाका (!) वर्ण का उपयोग किया है (या आप की तरह कुछ भी उपयोग करें) जो सामान्य से बचा जाता है, लेकिन विभाजक के रूप में आपके द्वारा केवल-पसंद-ही-फॉरवर्ड स्लैश का उपयोग करता है।


3
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 

जहां VAR में वह है जिसमें आप फ़ील्ड को बदलना चाहते हैं


3

Sed के भीतर VARIABLES से निपटना

[root@gislab00207 ldom]# echo domainname: None > /tmp/1.txt

[root@gislab00207 ldom]# cat /tmp/1.txt

domainname: None

[root@gislab00207 ldom]# echo ${DOMAIN_NAME}

dcsw-79-98vm.us.oracle.com

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g'

 --- Below is the result -- very funny.

domainname: ${DOMAIN_NAME}

 --- You need to single quote your variable like this ... 

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g'


--- The right result is below 

domainname: dcsw-79-98vm.us.oracle.com

मैं Azure DevOps YAML पाइपलाइनों में यह काम पाने के लिए संघर्ष कर रहा था। इस टिप्पणी ने मुझे कुछ कॉन्फ़िगरेशन फ़ाइलों को टोकन करने के लिए सफलतापूर्वक इस ट्रिक का उपयोग करने में मदद की।
औरोव

1

मुझे इसी तरह की समस्या थी, मेरी एक सूची थी और मुझे टेम्पलेट के आधार पर एक एसक्यूएल स्क्रिप्ट बनानी होगी (जिसमें @INPUT@प्रतिस्थापित करने के लिए तत्व के रूप में शामिल ):

for i in LIST 
do
    awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.