फ़ाइल ढूंढें और बदलें ओवरराइट फ़ाइल काम नहीं करती है, यह फ़ाइल को खाली करती है


604

मैं कमांड लाइन के माध्यम से एक HTML फ़ाइल को ढूंढना और बदलना चाहता हूं।

मेरी आज्ञा कुछ इस प्रकार है:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

जब मैं इसे चलाता हूं और बाद में फ़ाइल को देखता हूं, तो यह खाली है। इसने मेरी फ़ाइल की सामग्री को हटा दिया।

जब मैं फ़ाइल को फिर से बहाल करने के बाद इसे चलाता हूं:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

stdoutफ़ाइल की सामग्री है, और खोज और बदल मार डाला गया है।

ये क्यों हो रहा है?


13
पर्ल विकल्प:perl -pi -w -e 's/STRING_TO_REPLACE/REPLACE_WITH/g;' index.html
Gjorgji Tashkovski

sedएक तार को खोजने और पूरी लाइन को बदलने के लिए बहुत संबंधित आदेश: stackoverflow.com/questions/11245144/…
cregox

जवाबों:


917

जब शेल> index.html कमांड लाइन में देखता है तो यह लिखने केindex.html लिए फाइल को खोलता है , अपने पिछले सभी सामग्रियों को मिटा देता है।

इसे ठीक करने के लिए आपको परिवर्तनों को इनलाइन करने और मूल फ़ाइल का बैकअप बनाने से पहले उस स्थान में परिवर्तन करने के लिए -iविकल्प को sedपास करना होगा:

sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

.Bak के बिना कमांड मैक ओएसएक्स जैसे कुछ प्लेटफार्मों पर विफल हो जाएगा।


20
शायद truncates the fileइसके बजाय कहने opens the fileसे यह स्पष्ट हो जाता है।
मिकेल

12
कम से कम मेरे मैक पर, पहला सुझाव काम नहीं करता है ... यदि आप एक फ़ाइल पर इन-प्लेस प्रतिस्थापन कर रहे हैं, तो आपको एक एक्सटेंशन निर्दिष्ट करना होगा। आप कम से कम, एक शून्य-लंबाई विस्तार में पास कर सकते हैं: sed -i 's / STRING_TO_REPLACE / STRING_TO_REPLACE_IT / g index.html
टॉम लियानजा

5
चर के लिए sed -i.bak की / '$ खोज' / '$ की जगह' / g 'index.html
फातिमा ज़ोहरा

33
osx पर, -i के पैरामीटर के रूप में एक रिक्त स्ट्रिंग '' का उपयोग करें, जैसे:sed -i '' 's/blah/xx/g'
पियरे ह्यूस्टन

4
लेकिन तुम्हारे .bakबाद क्या है sed -i?
पैट्रीज़ियो बर्तोनी

210

एक वैकल्पिक, उपयोगी, पैटर्न है:

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

-iविकल्प का उपयोग किए बिना इसका बहुत अधिक प्रभाव पड़ता है, और इसके अतिरिक्त इसका मतलब है कि, अगर किसी कारण से सेड स्क्रिप्ट विफल हो जाती है, तो इनपुट फ़ाइल बंद नहीं होती है। इसके अलावा, यदि संपादन सफल होता है, तो कोई बैकअप फ़ाइल नहीं बची रहती है। इस तरह के मुहावरे मेकफाइल्स में उपयोगी हो सकते हैं।

बहुत सारे सेड का -iविकल्प है, लेकिन उन सभी का नहीं; पॉज़िक्स सेड वह है जो नहीं करता है। यदि आप पोर्टेबिलिटी के लिए लक्ष्य कर रहे हैं, इसलिए, यह सबसे अच्छा है।


9
+1 कोई बैकअप फ़ाइल के चारों ओर बिछाने और संपादन विफल होने पर इनपुट फ़ाइल को क्लोबिंग नहीं करने के लिए। मैक पर निर्दोष रूप से काम किया।
माइक ग्रेस

मेरे लिए पूरी तरह से काम किया। धन्यवाद! (एक मैक पर)
रुचि

1
इसने मेरे लिए पूरी तरह से काम किया जहां Ubuntu सर्वर 14.04 sed -i ने फ़ाइल को शून्य करना जारी रखा।
क्रिस गिडिंग्स

2
बेहद मामूली वृद्धि:... && mv index.html{.tmp,}
एडवर्डगार्सन

5
@EdwardGarson वास्तव में, अगर मैं इसे टाइप कर रहा था तो शायद यही होगा कि मैं इसका उपयोग करूं - मैं मानता हूं कि यह बकवास है - लेकिन sh(अगर मैं सही तरीके से याद करता हूं) तो इसका {...}विस्तार नहीं है । Makefile में आप इसके shबजाय उपयोग कर सकते हैं bash, इसलिए यदि आप पोर्टेबिलिटी (या सकारात्मकता) के लिए लक्ष्य कर रहे हैं तो आपको इस निर्माण से बचना होगा।
नॉर्मन ग्रे

95
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

यह फ़ाइल index.html पर एक वैश्विक स्थानापन्न प्रतिस्थापन करता है। स्ट्रिंग का उद्धरण क्वेरी और प्रतिस्थापन में व्हाट्सएप के साथ समस्याओं को रोकता है।


57

sed के -i विकल्प का उपयोग करें, उदा

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html

इसका क्या मतलब है? sed: -आई का उपयोग स्टड के साथ नहीं किया जा सकता है
शीतल

2
उद्धरण में अपना पैटर्न घेरना याद रखें यदि इसमें व्हॉट्सएप हो -'s/STRING_TO_REPLACE/REPLACE_WITH/g'
डग थॉम्पसन

@sheetal: -iयथा-स्थान के प्रदर्शन पर ध्यान संपादन फ़ाइलें , तो यह इसके साथ गठबंधन करने के लिए मतलब नहीं है stdin इनपुट।
14

यह macOS पर काम कर सकता है, लेकिन यह मेरे लिए आर्क लिनक्स पर नहीं है।
xdevs23 13

-E के बिना, स्वीकृत जवाब MacOS, कैटालिना पर काम नहीं करता है। -ई के साथ यह काम करता है।
cwhiii

18

कई फ़ाइलों को बदलने के लिए (और * .bak के रूप में प्रत्येक के एक बैकअप को बचाने):

perl -p -i -e "s/\|/x/g" *  

निर्देशिका में सभी फ़ाइलों को लेने के लिए और जगह लेगा |साथ x यह एक "पर्ल पाई" कहा जाता है (आसान एक पाई के रूप में)


1
किसी को समस्या कथन को देखने के लिए तैयार देखना अच्छा है, न कि केवल टैग। ओपी sedआवश्यकता के रूप में निर्दिष्ट नहीं किया गया था , केवल इसका उपयोग किया था क्योंकि उपकरण पहले से ही कोशिश कर रहा है।
user7412956

14

आपको -iइन-प्लेस संपादन के लिए विकल्प का उपयोग करने का प्रयास करना चाहिए ।


6
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

यदि आपके पास जोड़ने के लिए एक लिंक है, तो यह प्रयास करें। ऊपर के रूप में URL के लिए खोजें (https के साथ शुरू और with.com यहाँ समाप्त) और इसे URL स्ट्रिंग के साथ बदलें। मैंने $pub_urlयहां एक चर का उपयोग किया है। sयहाँ खोज का gमतलब है और वैश्विक प्रतिस्थापन का मतलब है।

यह काम करता हैं !


6

चेतावनी: यह एक खतरनाक तरीका है! यह linux में i / o बफ़र्स को गाली देता है और बफ़र करने के विशिष्ट विकल्पों के साथ यह छोटी फ़ाइलों पर काम करने का प्रबंधन करता है। यह एक दिलचस्प जिज्ञासा है। लेकिन एक वास्तविक स्थिति के लिए इसका इस्तेमाल न करें!

आप के -iविकल्प के अलावा उपयोगिता काsed उपयोग कर सकते हैं ।tee

से man:

टी - मानक इनपुट से पढ़ें और मानक आउटपुट और फ़ाइलों को लिखें

तो, समाधान होगा:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html

- यहां teeयह सुनिश्चित करने के लिए दोहराया गया है कि पाइपलाइन बफ़र की गई है। तब पाइपलाइन में सभी कमांड अवरुद्ध हो जाते हैं जब तक कि उन्हें काम करने के लिए कुछ इनपुट नहीं मिलता है। पाइपलाइन में प्रत्येक कमांड तब शुरू होती है जब अपस्ट्रीम कमांड्स ने कमांड के इनपुट को बाइट्स का 1 बफर (आकार कहीं परिभाषित किया गया है ) लिखा है । तो अंतिम कमांड tee index.html, जो लिखने के लिए फ़ाइल को खोलता है और इसलिए इसे खाली करता है, अपस्ट्रीम पाइपलाइन के समाप्त होने के बाद चलता है और आउटपुट पाइप लाइन के भीतर बफर में है।

सबसे अधिक संभावना है कि निम्नलिखित काम नहीं करेगा:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html

- यह बिना किसी अवरोध के एक ही समय में पाइपलाइन के दोनों कमांड चलाएगा। (पाइप लाइन अवरुद्ध बिना बफर द्वारा बफर के बजाय लाइन द्वारा बाइट्स लाइन पास करना चाहिए। जब आप चलाने के रूप में एक ही cat | sed s/bar/GGG/अवरुद्ध इसे और अधिक इंटरैक्टिव है और आम तौर पर सिर्फ 2 आदेशों की पाइपलाइनों बफरिंग और अवरुद्ध के बिना चलने के बिना।। अब पाइपलाइनों बफ़र कर रहे हैं।) tee index.htmlइच्छा लिखने के लिए फ़ाइल खोलें और इसे खाली कर दिया जाएगा। हालाँकि, यदि आप हमेशा बफ़रिंग चालू करते हैं, तो दूसरा संस्करण भी काम करेगा।


3
टी की आउटपुट फ़ाइल भी तुरंत खोली जाती है जिसके परिणामस्वरूप पूरे कमांड के लिए एक खाली इंडेक्स। Html होता है।
sjngm

3
यह किसी भी इनपुट फ़ाइल को भ्रष्ट करेगा जो पाइपलाइन बफर से बड़ा है (जो कि आमतौर पर 64KB है) । (@ sjngm: फ़ाइल को तुरंत ही छोटा नहीं किया जाता है >, लेकिन बिंदु यह है कि यह एक टूटा हुआ समाधान है जिसके परिणामस्वरूप डेटा हानि हो सकती है)।
14

4

कमांड के साथ समस्या

sed 'code' file > file

fileइससे पहले कि यह वास्तव में इसे संसाधित करने के लिए हो जाता है से पहले शेल द्वारा छंटनी की जाती है। नतीजतन, आपको एक खाली फ़ाइल मिलती है।

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

tmp=$(sed 'code' file); echo -n "$tmp" > file

अभी तक बेहतर, उपयोग printfके बजाय echoके बाद से echoप्रक्रिया की संभावना है \\के रूप में \कुछ गोले (जैसे पानी का छींटा) में:

tmp=$(sed 'code' file); printf "%s" "$tmp" > file

1
लिंक को संरक्षित करने के लिए +1। यह एक अस्थायी फ़ाइल के साथ भी काम करता है:sed 'code' file > file.tmp; cat file.tmp > file; rm file.tmp
डैशहोक्सहा

3

और edजवाब:

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

कोडैडक्ट ने जो उत्तर दिया था , उसे दोहराने के लिए , शेल पहले पुनर्निर्देशन को हैंडल करता है , "input.html" फ़ाइल को मिटा देता है, और फिर शेल "sed" कमांड को एक खाली फाइल को पारित करने के लिए आमंत्रित करता है।


2
त्वरित प्रश्न, क्यों लोग उत्तर के ed"संस्करण" sedदेते रहते हैं? क्या यह तेजी से प्रदर्शन करता है?
क्रेगॉक्स

6
कुछ जगह में संपादित sedकरने के -iलिए लागू नहीं है। edसर्वव्यापी है और आपको मूल फ़ाइल में अपने संपादन सहेजने देता है। साथ ही आपके किट में बहुत सारे टूल होना हमेशा अच्छा होता है।
ग्लेन जैकमैन

अच्छा ठीक है। इसलिए, प्रदर्शन के लिहाज से, मैं वही हूं जो मुझे लगता है। धन्यवाद!
क्रेगॉक्स

2

आप पूर्व मोड में विम का उपयोग कर सकते हैं:

ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
  1. % सभी लाइनों का चयन करें

  2. x सहेजें और बंद करें


0

मैं उस विकल्प की तलाश कर रहा था जहां मैं लाइन रेंज को परिभाषित कर सकता हूं और उत्तर पा सकता हूं। उदाहरण के लिए, मैं host1 को host2 से पंक्ति 36-57 में बदलना चाहता हूं।

sed '36,57 s/host1/host2/g' myfile.txt > myfile1.txt

चरित्र के मामले को अनदेखा करने के लिए आप gi विकल्प का उपयोग कर सकते हैं।

sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt

0

उपरोक्त सही उत्तरों के लिए सभी सम्मान के साथ, यह हमेशा की तरह "ड्राई रन" स्क्रिप्ट के लिए एक अच्छा विचार है, ताकि आप अपनी फ़ाइल को भ्रष्ट न करें और फिर से खरोंच से शुरू करें।

फ़ाइल को लिखने के बजाय आउटपुट लाइन को कमांड लाइन में फैलाने के लिए बस अपनी स्क्रिप्ट प्राप्त करें, उदाहरण के लिए, जैसे:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

या

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

इस तरह आप अपनी फ़ाइल को काटे बिना कमांड के आउटपुट को देख और जांच सकते हैं।

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