शेल स्क्रिप्ट में दूसरे स्ट्रिंग के लिए एक सबरिंग बदलें


820

मेरे पास "मैं सूजी और शादी से प्यार करता हूं" और मैं "सूजी" को "सारा" में बदलना चाहता हूं।

#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...

परिणाम इस तरह होना चाहिए:

firstString="I love Sara and Marry"

15
मैं सूजी को धीरे से नीचे आने देता हूँ। :)
कोडनिफर 20

यह आप नहीं मैं हूँ ! सुजी से बात करने के लिए स्ट्रिंग होना चाहिए था
GoodSp33d

जवाबों:


1357

किसी दिए गए स्ट्रिंग के साथ एक पैटर्न की पहली घटना को बदलने के लिए , उपयोग करें :${parameter/pattern/string}

#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"    
# prints 'I love Sara and Marry'

सभी घटनाओं को बदलने के लिए , उपयोग करें :${parameter//pattern/string}

message='The secret code is 12345'
echo "${message//[0-9]/X}"           
# prints 'The secret code is XXXXX'

(यह में प्रलेखित है बैश संदर्भ मैनुअल , §3.5.3 "शैल पैरामीटर विस्तार" ।)

ध्यान दें कि यह सुविधा POSIX द्वारा निर्दिष्ट नहीं है - यह एक बैश एक्सटेंशन है - इसलिए सभी यूनिक्स गोले इसे लागू नहीं करते हैं। प्रासंगिक POSIX प्रलेखन के लिए, ओपन ग्रुप टेक्निकल स्टैंडर्ड बेस स्पेसिफिकेशन्स, अंक 7 , शेल एंड यूटिलिटीज वॉल्यूम, Par2.6.2 "पैरामीटर एक्सपेंशन" देखें


3
@ruakh मैं इस कथन को या शर्त के साथ कैसे लिख सकता हूँ। बस अगर मैं सूजी या शादी को नए तार से बदलना चाहता हूं।
प्रियतम

3
@ Priyatham51: इसके लिए कोई अंतर्निहित सुविधा नहीं है। बस एक की जगह, फिर दूसरे की।
बरखा

4
@Bu: नहीं, क्योंकि \nउस संदर्भ में एक नई पंक्ति नहीं बल्कि खुद का प्रतिनिधित्व करेंगे। मैं परीक्षण करने के लिए अब बैश काम सही नहीं है, लेकिन आप की तरह कुछ लिखने के लिए सक्षम होना चाहिए, $STRING="${STRING/$'\n'/<br />}"। (हालांकि आप शायद चाहते हैं STRING//- प्रतिस्थापित-सभी - बस के बजाय STRING/।)
सितंबर को

25
स्पष्ट होने के लिए, क्योंकि यह मुझे थोड़ा भ्रमित करता है, पहले भाग को एक चर संदर्भ होना चाहिए। तुम नहीं कर सकते echo ${my string foo/foo/bar}। आपको आवश्यकता होगीinput="my string foo"; echo ${input/foo/bar}
हेनरिक एन

2
@mgutt: यह उत्तर संबंधित प्रलेखन के लिए लिंक है। दस्तावेज़ीकरण सही नहीं है - उदाहरण के लिए, //सीधे उल्लेख करने के बजाय , यह उल्लेख करता है कि क्या होता है "यदि पैटर्न ' /' 'से शुरू होता है " (जो कि सटीक भी नहीं है, क्योंकि शेष वाक्य मानता है कि अतिरिक्त /वास्तव में हिस्सा नहीं है पैटर्न) - लेकिन मुझे किसी भी बेहतर स्रोत का पता नहीं है।
बर्बाद करें

208

यह पूरी तरह से बैश स्ट्रिंग हेरफेर के साथ किया जा सकता है:

first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}

यह केवल पहली घटना की जगह लेगा; उन सभी को बदलने के लिए, पहले स्लैश को दोगुना करें:

first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"

9
वैश्विक प्रतिस्थापन विकल्प के साथ स्वीकार किए गए एक को संपादित करने के बजाय, एक उत्तर को स्वीकार करने का क्या मतलब है? और उस regexps को जोड़ने का समर्थन किया जाता है, जबकि उस पर। और समझा रहा है कि "खराब प्रतिस्थापन" के साथ क्या हो रहा है। आपके पास पर्याप्त अंक हैं, @ केविन :)
डैन डस्केलस्कु

6
ऐसा प्रतीत होता है कि वे दोनों एक ही मिनट में जवाब देते हैं: ओ
जेमी हटर

76

डैश के लिए पिछले सभी पोस्ट काम नहीं कर रहे हैं

POSIX shसंगत समाधान है:

result=$(echo "$firstString" | sed "s/Suzi/$secondString/")

1
मुझे यह मिल गया: $ इको $ (इको $ फर्स्टस्ट्रिंग | sed / szi / $ सेकंडस्ट्रीमिंग / g ') मुझे $ सेकंड स्ट्रींग और शादी से प्यार है
Qstnr_La

2
: चर प्रतिस्थापन के लिए दोहरे उद्धरण चिह्नों का उपयोग @Qstnr_Laresult=$(echo $firstString | sed "s/Suzi/$secondString/g")
ईएमसी

1
प्लस 1 एक चर के रूप में अच्छी तरह से उत्पादन करने के लिए कैसे दिखाने के लिए। धन्यवाद!
शेफ फिरौन

2
मैंने एकल उद्धरण तय किए और echoतर्क के आसपास लापता उद्धरण भी जोड़े । यह भ्रामक रूप से सरल तारों के साथ उद्धृत किए बिना काम करता है, लेकिन आसानी से किसी भी nontrivial इनपुट स्ट्रिंग (अनियमित रिक्ति, शेल मेटाचैकर, आदि) पर टूट जाता है।
ट्रिपल

श (AWS कोडबिल्ट / उबंटू श) में मैंने पाया कि मुझे अंत में सिंगल स्लैश की आवश्यकता है, दोहरे की नहीं। मैं टिप्पणी को संपादित करने जा रहा हूं क्योंकि ऊपर की टिप्पणियां भी एक ही स्लैश दिखाती हैं।
टिम

67

इसे इस्तेमाल करे:

 sed "s/Suzi/$secondString/g" <<<"$firstString"

19
आपको इसके लिए वास्तव में सेड की आवश्यकता नहीं है; बैश मूल रूप से इस तरह के प्रतिस्थापन का समर्थन करता है।
16

12
मुझे लगता है कि यह "बैश" टैग है, लेकिन यहां आया क्योंकि एक और शेल के लिए कुछ सरल की आवश्यकता थी। यह wiki.ubuntu.com/ क्या है के लिए यह एक अच्छा रसीला विकल्प है। यह ऐसा लगता है जैसे मुझे चाहिए।
22

3
यह राख / पानी का छींटा या किसी अन्य पोसिक्स श के लिए बहुत अच्छा काम करता है।
योशुआ वुएट्स

2
मुझे त्रुटि sed: -e अभिव्यक्ति # 1, char 9: अज्ञात विकल्प `s
Nam G VU

1
पहला जवाब जो स्टडिन के साथ काम करता है, जो पाइपलाइनिंग स्ट्रिंग्स के लिए बहुत अच्छा है।
दीनी

46

sedयदि स्ट्रिंग्स में RegExp वर्ण हैं , तो इसका उपयोग करना बेहतर है ।

echo ${first_string/Suzi/$second_string}

यह विंडोज के लिए पोर्टेबल है और कम से कम पुराने के साथ काम करता है जैसे कि बैश 3.1।

यह दिखाने के लिए कि आपको इसे टालने की ज़रूरत नहीं है, यह दिखाने के लिए:

/home/name/foo/bar

इस मामले में:

~/foo/bar

लेकिन केवल अगर /home/nameशुरुआत में है। हमें जरूरत नहीं है sed!

यह देखते हुए कि बैश हमें जादुई चर देता है $PWDऔर $HOMEहम कर सकते हैं:

echo "${PWD/#$HOME/\~}"

संपादित करें: उद्धरण / बचने पर नोट के लिए टिप्पणियों में मार्क हैफर्कैम्प के लिए धन्यवाद ~। "

ध्यान दें कि कैसे चर $HOMEमें स्लैश होते हैं लेकिन यह कुछ भी नहीं तोड़ता है।

आगे पढ़ें: उन्नत बैश-पटकथा गाइड
यदि उपयोग sedकरना आवश्यक है, तो हर चरित्र से बचना सुनिश्चित करें ।


प्रत्येक बार मेरे कस्टम चलने पर एक नए चर को परिभाषित करने से बचने के लिए इस उत्तर ने मुझे कमांड का उपयोग sedकरने से रोक दिया । बैश स्ट्रिंग प्रतिस्थापन के लिए एक कमांड के आउटपुट का उपयोग करने के लिए जादू चर की तुलना में अधिक सामान्य तरीका प्रदान करता है? आपके कोड के लिए, मुझे बैश को $ HOME में विस्तारित करने से बचने के लिए बचना पड़ा । इसके अलावा, आपकी आज्ञा में क्या है? pwd$PS1~#
मार्क हैफर्कैम्प

1
@MarkHaferkamp इस देखें से "आगे पठन सिफारिश की" लिंक। "भागने" के बारे में ~: ध्यान दें कि मैंने सामान कैसे उद्धृत किया। हमेशा सामान उद्धृत करने के लिए याद रखें! और यह सिर्फ जादुई चर के लिए काम नहीं करता है: कोई भी चर प्रतिस्थापन के लिए सक्षम है, स्ट्रिंग की लंबाई, और अधिक, बैश के भीतर। अपने $PS1उपवास की कोशिश करने के लिए बधाई : आप भी दिलचस्पी ले $PROMPT_COMMANDसकते हैं यदि आप किसी अन्य प्रोग्रामिंग भाषा में अधिक सहज हैं और एक संकलित संकेत को कोड करना चाहते हैं।
कैमिलो मार्टिन

"आगे पढ़ने" लिंक "#" बताते हैं। बैश 4.3.30 पर, echo "${PWD/#$HOME/~}"मेरे को प्रतिस्थापित नहीं करता $HOMEसाथ ~~साथ \~या '~'काम से प्रतिस्थापित करना । इनमें से कोई भी बैश 4.2.53 पर एक और डिस्ट्रो पर काम करता है। क्या आप ~बेहतर संगतता के लिए बोली या भागने के लिए अपनी पोस्ट को अपडेट कर सकते हैं ? मेरे "मैजिक वेरिएबल्स" प्रश्न का क्या मतलब था: क्या मैं बैश के वैरिएबल सबस्टेशन का उपयोग कर सकता हूं, उदाहरण के लिए, unameइसे पहले वेरिएबल के रूप में सहेजे बिना? मेरे व्यक्तिगत के लिए $PROMPT_COMMAND, यह जटिल है
मार्क हैफर्कैम्प

@MarkHaferkamp वाह, आप पूरी तरह से सही हैं, मेरा बुरा। अब जवाब को अपडेट करेंगे।
कैमिलो मार्टिन

1
@MarkHaferkamp बैश और इसके अस्पष्ट नुकसान ...: पी
कैमिलो मार्टिन

19

अगर कल आप तय करते हैं कि आपको शादी से प्यार नहीं है, तो उसे भी बदला जा सकता है:

today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt

अपने प्रेमी को छोड़ने के 50 तरीके होने चाहिए।


9

चूंकि मैं एक टिप्पणी नहीं जोड़ सकता। @ruaka उदाहरण को अधिक पठनीय बनाने के लिए इसे इस तरह लिखें

full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}

जब तक मैं आपके उदाहरण पर आया, मैंने आदेश को दूसरे तरीके से समझ लिया था। इससे स्पष्ट हुआ कि क्या हो रहा है
raghav710

5

शुद्ध POSIX खोल विधि है, जो विपरीत रोमन Kazanovskyi की sedआधारित जवाब कोई बाहरी उपकरण की जरूरत है, सिर्फ खोल के अपने देशी पैरामीटर विस्तार । ध्यान दें कि लंबे फ़ाइल नाम को छोटा किया जाता है ताकि कोड एक पंक्ति में बेहतर हो सके:

f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"

आउटपुट:

I love Sara and Marry

यह काम किस प्रकार करता है:

  • सबसे छोटा प्रत्यय पैटर्न निकालें। "${f%$t*}"" I love" यदि प्रत्यय $t" Suzi*" $f" " में है। I love Suzi and Marry

  • लेकिन अगर t=Zelda, फिर "${f%$t*}"कुछ भी नहीं हटाता है, और पूरे स्ट्रिंग को लौटाता है " I love Suzi and Marry"।

  • यह परीक्षण करने के लिए इस्तेमाल करता है, तो है $tहै में $fसे [ "${f%$t*}" != "$f" ]जो करने के लिए मूल्यांकन करेंगे सच है, तो $fस्ट्रिंग है " Suzi*" और झूठी नहीं तो।

  • यदि परीक्षण रिटर्न सच , का उपयोग कर वांछित स्ट्रिंग निर्माण निकालें सबसे छोटा प्रत्यय पैटर्न ${f%$t*} " I love" और सबसे छोटा उपसर्ग पैटर्न निकालें ${f#*$t} " and Marry", के साथ 2 स्ट्रिंग $s" Sara" के बीच में।


5

मुझे पता है कि यह पुराना है, लेकिन जब से किसी ने awk का उपयोग करने के बारे में उल्लेख नहीं किया है:

    firstString="I love Suzi and Marry"
    echo $firstString | awk '{gsub("Suzi","Sara"); print}'

1
यदि आप विभाजित करने का प्रयास कर रहे हैं तो जाने का यह तरीका वास्तव में एक चर में नहीं बल्कि एक पाठ फ़ाइल में है। धन्यवाद, @ श्याम!
फेलिप एसएस श्नाइडर

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