मैं एक स्थानापन्न प्रतिस्थापन के LHS और RHS में चर का उपयोग कैसे कर सकता हूं?


60

मैं करना चाहता हूँ:

cat update_via_sed.sh | sed 's/old_name/new_name/' > new_update_via_sed.sh

मेरे कार्यक्रम में।

लेकिन मैं चर का उपयोग करना चाहता हूं, जैसे

old_run='old_name_952'
new_run='old_name_953'

मैंने उनका उपयोग करने की कोशिश की है लेकिन प्रतिस्थापन नहीं होता है (कोई त्रुटि नहीं)। मैंने कोशिश की है:

cat update_via_sed.sh | sed 's/old_run/new_run/'
cat update_via_sed.sh | sed 's/$old_run/$new_run/'
cat update_via_sed.sh | sed 's/${old_run}/${new_run}/'

2
आप एक कमांड तर्क में उपयोग पैरामीटर का जवाब पा सकते हैं ।
16

जवाबों:


44

तुम यह कर सकते थे:

sed "s/$old_run/$new_run/" < infile > outfile

लेकिन सावधान रहना है कि $old_runएक नियमित रूप से अभिव्यक्ति के रूप में लिया जाएगा और इसलिए किसी भी विशेष वर्ण हैं जो चर होता है, इस तरह के रूप /या .करने के लिए होता फरार हो जा । इसी तरह, में $new_run, &और \पात्रों को विशेष रूप से इलाज करने की आवश्यकता होगी और आपको इसमें /और नए अक्षरों से बचना होगा।

अगर की सामग्री $old_runया $new_runअपने नियंत्रण में नहीं है, तो यह है कि भागने प्रदर्शन करने के लिए महत्वपूर्ण है, या अन्यथा कि कोड एक कोड इंजेक्शन भेद्यता के बराबर है


3
मैं सीड परम में एकल उद्धरण का उपयोग कर रहा था, दोहरे उद्धरण चिह्नों पर स्विच किया गया और यह फ़ाइल काम कर गया। बहुत बढ़िया।
आकाश

ऐसा नहीं है कि sedअकेले रेगेक्स का उपयोग नहीं करेगा, लेकिन sed -Eकरेगा?
कीवी

@ कीवी, नहीं। -eएक sed xpression निर्दिष्ट करने के लिए है , ताकि आप एक से अधिक (के रूप में sed -e exp1 -e exp2) या फ़ाइलों और अभिव्यक्ति ( sed -f file -e exp) के संयोजन पारित कर सकते हैं । आप भ्रमित हो सकते हैं कि -Eकुछ कार्यान्वयन के साथ, BRE के बजाय EREs का उपयोग करने के लिए sed को बताता है।
स्टीफन चेज़लस

मैंने गलती की, लेकिन ठीक है, यह बताएं कि मेरे पास बिना सीड का उपयोग किए इतने सारे मुद्दे क्यों हैं, -Eमैं केवल विस्तारित रेगेक्स को ही नियमित नहीं करता। एक्सप्लानेटॉन के लिए धन्यवाद।
कीवी

@ कीवी, अभी भी नियमित अभिव्यक्ति सिंटैक्स के लिए कुछ कार्यान्वयनों द्वारा समर्थित अधिक विकल्पों के लिए लिंक किए गए प्रश्नोत्तर देखें sed
स्टीफन चेजलस

31

यह काम किया:

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/'

जैसा कि मैं उसी फ़ाइल को 'पुन: उपयोग' करना चाहता हूं, जो वास्तव में इसी तरह के दृष्टिकोण की इच्छा रखने वाले किसी व्यक्ति के लिए उपयोग करता है:

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/' > new_update; mv -f new_update update_via_sed.sh

ऊपर एक नई फ़ाइल बनाई गई तो वर्तमान फ़ाइल को नई फ़ाइल का नाम बदलने की तुलना में वर्तमान फ़ाइल को हटा देती है।


4
जब तक आप उनमें विशेष वर्ण नहीं रखते, आपको बिल्ली, mv, या अतिरिक्त '' की आवश्यकता नहीं है। तो यह है sed -i s/"$old"/"$new"/ update_via_sed.sh। हालाँकि इस बात का ध्यान रखें कि यह पुराने और नए के किसी भी मूल्य के लिए काम नहीं करता है। उदाहरण के लिए इसमें शामिल नहीं होना चाहिए / आदि, क्योंकि $ पुराना अभी भी एक खोज और $ नया एक प्रतिस्थापन पैटर्न है जहां कुछ वर्णों के विशेष अर्थ हैं।
ठंढकुट्ज़

1
sed -i "s/$old/$new/"भी ठीक है (उपरोक्त सावधानियों के साथ)। sedआमतौर पर विभाजक को sकमांड के बाद पहला चरित्र मानता है - यानी अगर आपके चरों में स्लैश होते हैं, /लेकिन इसे कहने नहीं देते ( @), तो आप "$ @ पुराने @ $ नए @" का उपयोग कर सकते हैं।
पेट्रफ

22

जब तक आप दोहरे उद्धरण चिह्नों (एक उद्धरण नहीं) में तब तक चर का उपयोग कर सकते हैं:

sed "s/$var/r_str/g" file_name >new_file

यदि आपके पास /वेरिएबल में फ़ॉरवर्ड स्लैश ( ) है तो नीचे की तरह अलग विभाजक का उपयोग करें

sed "s|$var|r_str|g" file_name >new_file

1
दोहरी उद्धरणों का उपयोग करने की आवश्यकता का उल्लेख करने के लिए +1। यही मेरी समस्या थी।
speckledcarp

1
वास्तव में क्या मैं, के लिए देख रहा था के उपयोग सहित |मेरे मामले में के रूप में, चर तो यह है एक पथ है /उस में
yorch

कुछ कारणों से पाइप |ने मेरे लिए मैकओएस 10.14 पर काम किया, लेकिन अन्य सेपरेटर जैसे कि @या #नहीं। मैंने अपने env var में भी स्लैश फॉरवर्ड किया था।
डेविंडके

21

'इन-प्लेस' sed (usng -i ध्वज) उत्तर था। पेट्रफ के लिए धन्यवाद।

sed -i "s@$old@$new@" file

2
आपके पास गलत जगह पर उद्धरण हैं। उद्धरण चर के आसपास होने चाहिए, नहीं s@(जो किसी भी तरह से शेल के लिए विशेष नहीं है)। सबसे अच्छा सब कुछ अंदर उद्धरण की तरह डाल दिया है sed -i "s@$old@$new@" file। ध्यान दें कि -iएक मानक sedविकल्प नहीं है ।
स्टीफन चेज़लस

मैं $इस आदेश में कैसे बच सकता हूं । जैसे, मैं $xxxएक चर के मान में संपूर्ण परिवर्तन करने जा रहा हूं $JAVA_HOME। मैंने कोशिश की sed -i "s@\$xxx@$JAVA_HOME@" file, लेकिन त्रुटि कहती हैno previous regular expression
हकुनामी

3

man bash यह एकल उद्धरण के बारे में देता है

एकल उद्धरणों में वर्णों को संलग्न करना प्रत्येक वर्ण के शाब्दिक मूल्य को उद्धरणों के भीतर संरक्षित करता है। एकल उद्धरण के बीच एक एकल उद्धरण नहीं हो सकता है, तब भी जब एक बैकस्लैश द्वारा पूर्ववर्ती हो।

जो भी आप कमांड लाइन पर टाइप करते हैं, बैश इसे व्याख्या करता है और फिर यह उस प्रोग्राम को परिणाम भेजता है जिसे इसे भेजा जाना चाहिए। इस मामले में, यदि आप उपयोग करते हैं sed 's/$old_run/$new_run/', तो bash सबसे पहले sedइसे देखता है , इसे $PATHवैरिएबल में मौजूद एक निष्पादन योग्य के रूप में पहचानता है । sedनिष्पादन एक इनपुट की आवश्यकता है। बैश इनपुट ढूंढता है और पाता है 's/$old_run/$new_run/'। सिंगल कोट्स का कहना है कि उनमें मौजूद कंटेंट की व्याख्या न करें और उन्हें वैसे ही पास करें। तो, बैश तो उन्हें sed करने के लिए गुजरता है। सेड एक त्रुटि देता है क्योंकि $केवल पंक्ति के अंत में हो सकता है।

इसके बजाय अगर हम दोहरे उद्धरण चिह्नों का उपयोग करते हैं, यानी, "s/$old_run/$new_run/"तो बैश इसे देखता है और $old_runएक चर नाम के रूप में व्याख्या करता है और एक प्रतिस्थापन बनाता है (इस चरण को चर विस्तार कहा जाता है)। यह वास्तव में हम क्या आवश्यकता है।

लेकिन, आपको दोहरे उद्धरण चिह्नों का उपयोग करके सावधान रहना होगा क्योंकि, उन्हें पहले बैश द्वारा व्याख्या किया जाता है और फिर sed को दिया जाता है। तो, कुछ प्रतीक जैसे `का उपयोग करने से पहले बच जाना चाहिए।


1

फ़्लिपेंट होने के जोखिम पर - क्या आपने विचार किया है perl

कौन सी - अन्य चीजों के बीच - 'सेड स्टाइल' ऑपरेशन करने में काफी अच्छा है, लेकिन यह भी एक पूरी तरह से चित्रित प्रोग्रामिंग चीज़ है।

यह आपके उदाहरण में दिखता है , जो आप वास्तव में करने की कोशिश कर रहे हैं वह संख्या में वृद्धि है।

तो कैसे के बारे में:

#!/usr/bin/env perl
use strict;
use warnings 'all'; 

while ( <DATA> ) {
    s/old_name_(\d+)/"old_name_".($1+1)/e;
    print;
}

__DATA__
old_name_932

या एक लाइनर के रूप में - sed शैली:

perl -pe 's/old_name_(\d+)/"old_name_".($1+1)/e'

1
$ echo $d1 | sed -i 's/zkserver1/'${d1}'/g' deva_file
sed: -e expression #1, char 26: unterminated `s' command 

में $d1मैं मूल्यों को संचय कर रहा हूं

मैं वैरिएबल से मान को प्रतिस्थापित नहीं कर सकता, इसलिए मैंने निम्नलिखित कमांड की कोशिश की जो यह काम कर रहा है

echo $d1 | sed -i 's/zkserver1/'"${d1}"'/g' deva_file

गुम दोहरे उद्धरण चिह्न में "${d1}", वह त्रुटि थी


-2

मान लिया गया है $old_runऔर $new_runपहले से ही सेट हैं:

cat update_via_sed.sh | eval $(print "sed 's/$old_run/$new_run/g'")

यह स्क्रीन पर परिवर्तन दिखाता है। जरूरत पड़ने पर आप आउटपुट को रीडायरेक्ट कर सकते हैं।


-2

Sed में एक चर का उपयोग करने के लिए, दोहरे उद्धरण चिह्नों का उपयोग करें ", चर को संलग्न करने के लिए, उस पैटर्न में जिसका आप उपयोग कर रहे हैं। उदाहरण के लिए: a = "Hi" यदि आप एक पैटर्न में 'a' को जोड़ना चाहते हैं, तो आप नीचे उपयोग कर सकते हैं: sed -n "1, / pattern" $ {a} "pattern / p" फ़ाइल नाम


2
के विस्तार को $aयहां रेखांकित किया गया है, जिसका अर्थ है कि इसके मूल्य में कोई भी स्थान शेल में शब्द विभाजन को आमंत्रित करेगा।
Kusalananda

-2

आप पर्ल का उपयोग भी कर सकते हैं:

perl -pi -e ""s/$val1/$val2/g"" file

उन चर पर विचार करें जिनके मान में रिक्त स्थान हो सकते हैं। पर्ल अभिव्यक्ति के आसपास के खाली तार ""कुछ भी नहीं करेंगे।
Kusalananda

-2

तार तोड़ना

bad => linux एक स्ट्रिंग देखें $ old_run:

sed 's/$old_run/$new_run/'

अच्छा => लिनक्स एक चर $ पुराने_रुन देखें:

sed 's/'$old_run'/'$new_run'/'

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