जगह में sed संपादित करें फ़ाइल


298

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


7
-iग्नू सेड में एक विकल्प है, लेकिन मानक सेड में नहीं है। हालाँकि, यह सामग्री को एक नई फ़ाइल में स्ट्रीम करता है और फिर फ़ाइल का नाम बदल देता है, इसलिए यह वह नहीं है जो आप चाहते हैं।
विलियम पर्सेल

2
वास्तव में, यह वही है जो मैं चाहता हूं, मैं चाहता हूं कि नई फ़ाइल को मूल नाम पर नाम बदलने का सांसारिक कार्य करने के लिए उजागर न किया जाए
उभयलिंगी

3
फिर आपको प्रश्न को पुनर्स्थापित करने की आवश्यकता है।
विलियम परसेल

3
@amphibient: क्या आप अपने प्रश्न के शीर्षक को 'सोलारिस' शब्द के साथ जोड़कर देखेंगे? आपके प्रश्न का मूल्य नष्ट हो रहा है। कृपया मेरे उत्तर के नीचे टिप्पणी देखें। धन्यवाद।
स्टीव

1
@ संदर्भ: मैंने सोलारिस उपसर्ग को फिर से शीर्षक से हटा दिया क्योंकि यह सोलारिस के लिए विशेष साधन नहीं है।
20

जवाबों:


475

-iविकल्प एक नई फ़ाइल में संपादित सामग्री वैसे भी धाराओं और फिर पर्दे के पीछे यह नाम बदलता है,।

उदाहरण:

sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

तथा

sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

macOS पर ।


3
कम से कम यह मेरे लिए ऐसा करता है तो मुझे करने की जरूरत नहीं है
उभयलिंगी

2
आप अपने सिस्टम पर GNU सेड को संकलित करने का प्रयास कर सकते हैं, फिर।
चिरोबा

3
उदाहरण:sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
थेल्स Ceolin

2
यह पेरल सॉल्यूशन से बेहतर है। किसी भी तरह यह किसी भी .swap फ़ाइल नहीं बना .... धन्यवाद!
मैथ्स

3
@ मैथ्स: यह करता है, लेकिन शायद कहीं और या कम समय के लिए?
चोराबा

72

एक ऐसी प्रणाली पर जहां sedफाइलों को संपादित करने की क्षमता नहीं है, मुझे लगता है कि बेहतर समाधान का उपयोग करना होगा perl:

perl -pi -e 's/foo/bar/g' file.txt

हालाँकि यह एक अस्थायी फ़ाइल बनाता है, लेकिन यह मूल की जगह ले लेता है क्योंकि एक जगह पर प्रत्यय / एक्सटेंशन की आपूर्ति की गई है।


14
न केवल यह एक अस्थायी फ़ाइल बनाता है, यह हार्ड लिंक को भी तोड़ता है (जैसे, फ़ाइल की सामग्री को बदलने के बजाय, यह फ़ाइल को उसी नाम की नई फ़ाइल से बदल देता है।) कभी-कभी यह वांछित व्यवहार होता है, कभी-कभी यह। स्वीकार्य, लेकिन जब किसी फ़ाइल के कई लिंक होते हैं तो यह लगभग हमेशा गलत व्यवहार होता है।
विलियम पर्ससेल

3
@DwightSpencer: मेरा मानना ​​है कि पर्ल के बिना सभी सिस्टम टूट गए हैं। एक एकल कमांड आदेशों की एक श्रृंखला को रौंदता है जब कोई उन्नत अनुमतियाँ चाहता है और उसका उपयोग करना चाहिए sudo। मेरे मन में, यह सवाल है कि नवीनतम जीएनयू या बीएसडी को स्थापित किए बिना अस्थायी फ़ाइल को मैन्युअल रूप से बनाने और नाम बदलने से कैसे बचें sed। बस पर्ल का उपयोग करें।
स्टीव

4
@PetrPeller: वाक़ई? यदि आप प्रश्न को ध्यान से पढ़ते हैं, तो आप समझेंगे कि ओपी कुछ इस तरह से बचने की कोशिश कर रहा है sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt। सिर्फ इसलिए कि यथा-स्थान संपादन एक अस्थायी फ़ाइल का उपयोग कर नाम बदलने करता है, इसका मतलब यह नहीं कि वह / वह करना चाहिए जब विकल्प उपलब्ध नहीं है एक मैनुअल नाम बदलने प्रदर्शन करते हैं। वहाँ से बाहर अन्य उपकरण हैं जो वह कर सकता है / वह चाहता है, और पर्ल स्पष्ट पसंद है। यह मूल प्रश्न का उत्तर कैसे नहीं है?
स्टीव

2
@a_arias: आप सही कह रहे हैं; उसने किया। लेकिन वह वह हासिल नहीं कर सकता जो वह सोलारिस का उपयोग करना चाहता है sed। सवाल वास्तव में बहुत अच्छा था, लेकिन यह मूल्य उन लोगों द्वारा कम कर दिया गया है जो या तो मैन पेज नहीं पढ़ सकते हैं या फिर वास्तव में एसओ पर यहां सवाल पढ़ने के लिए परेशान नहीं हो सकते हैं ।
स्टीव

4
@ एडवर्डगर्सन: आईआईआरसी, सोलारिस जहाज पर्ल के साथ लेकिन पायथन या रूबी नहीं। और जैसा मैंने पहले कहा है, ओपी सोलारिस सेड का उपयोग करके वांछित परिणाम प्राप्त नहीं कर सकता है।
स्टीव

56

ध्यान दें कि OS X पर आपको इस कमांड को चलाते समय "अमान्य कमांड कोड" या अन्य अजीब त्रुटियों जैसी अजीब त्रुटियां हो सकती हैं। इस समस्या को हल करने के लिए प्रयास करें

sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>

इसका कारण यह है कि OSX संस्करण पर sed, -iविकल्प एक extensionतर्क की अपेक्षा करता है ताकि आपका कमांड वास्तव में extensionतर्क के रूप में पार्स हो और फ़ाइल पथ को कमांड कोड के रूप में व्याख्या की जाए। स्रोत: https://stackoverflow.com/a/19457213


1
यह ओएस एक्स की एक और विषमता है। सौभाग्य से, brew install gnu-sedएक PATHइच्छा के साथ आप जीएनयू संस्करण का उपयोग कर सकते हैं। उल्लेख करने के लिए धन्यवाद; एक निश्चित सिर खरोंच।
डग

23

निम्नलिखित मेरे मैक पर ठीक काम करता है

sed -i.bak 's/foo/bar/g' sample

हम नमूना फ़ाइल में बार के साथ फू की जगह ले रहे हैं। मूल फ़ाइल का बैकअप sample.bak में सहेजा जाएगा

बैकअप के बिना इनलाइन संपादन के लिए, निम्न कमांड का उपयोग करें

sed -i'' 's/foo/bar/g' sample

किसी भी तरह से बैकअप फ़ाइलों को रखने से कैसे रोकें?
पेट्र पेलर

@PetrPeller, आप उसी के लिए उल्लिखित कमांड का उपयोग कर सकते हैं ... sed -i '' s / foo / bar / g 'नमूना
minhas23

18

ध्यान देने वाली एक बात, sedअपने आप ही फाइलें नहीं लिख सकते क्योंकि sed का एकमात्र उद्देश्य "स्ट्रीम" पर एक संपादक के रूप में कार्य करना है (यानी स्टड, स्टडआउट, स्टडर, और अन्य >&nबफ़र्स, सॉकेट्स और इसी तरह की पाइपलाइन )। इसे ध्यान में रखते हुए आप teeआउटपुट को फाइल में वापस लिखने के लिए दूसरी कमांड का उपयोग कर सकते हैं । एक अन्य विकल्प सामग्री में पाइपिंग से एक पैच बनाना है diff

टी विधि

sed '/regex/' <file> | tee <file>

पैच विधि

sed '/regex/' <file> | diff -p <file> /dev/stdin | patch

अपडेट करें:

इसके अलावा, ध्यान दें कि पैच को आउटपुट के लाइन 1 से बदलने के लिए फाइल मिलेगी:

पैच को यह जानने की जरूरत नहीं है कि किस फाइल को एक्सेस करना है क्योंकि यह आउटपुट की पहली पंक्ति में अलग से पाया जाता है:

$ echo foobar | tee fubar

$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin
*** fubar   2014-03-15 18:06:09.000000000 -0500
--- /dev/stdin  2014-03-15 18:06:41.000000000 -0500
***************
*** 1 ****
! foobar
--- 1 ----
! fubar

$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin | patch
patching file fubar

2
/dev/stdin 2014-03-15, उत्तर 7 जनवरी - क्या आप एक समय यात्री हैं?
एड्रियन फ्रुविर्थ

Windows पर, msysgit का उपयोग करना, /dev/stdinमौजूद नहीं है, इसलिए आपको /dev/stdin'-' के साथ बदलना होगा , बिना उद्धरण के एक एकल हाइफ़न, इसलिए निम्नलिखित कमांड काम करना चाहिए:$ sed 's/oo/u/' fubar | diff -p fubar -$ sed 's/oo/u/' fubar | diff -p fubar - | patch
जिम राडेन

@ AdrianFrühwirth मेरे पास एक नीले रंग का पुलिस बॉक्स है जो कहीं न कहीं आसपास है और किसी कारण से वे मुझे काम पर डॉक्टर बुलाते हैं। लेकिन ईमानदारी से, ऐसा लगता है कि उस समय सिस्टम पर वास्तव में खराब घड़ी है।
ड्वाइट स्पेंसर

ये समाधान मुझे विशेष बफरिंग व्यवहार पर भरोसा करते हुए दिखते हैं। मुझे बड़ी फ़ाइलों के लिए संदेह है क्योंकि यह पढ़ते समय टूट सकता है, फ़ाइल पैच कमांड द्वारा नीचे बदलना शुरू हो सकती है, या टी कमांड द्वारा और भी बदतर हो सकती है जो फ़ाइल को छोटा कर देगी। वास्तव में मुझे यकीन नहीं है कि अगर patchयह भी छोटा नहीं होगा। मुझे लगता है कि दूसरी फाइल में आउटपुट सेव करना और फिर catओरिजिनल में सेव करना सुरक्षित होगा।
अकोस्टैडिनोव

@ william-pursell
akostadinov

11

आप जो चाहते हैं, वह करना संभव नहीं है sed। यहां तक sedकि उस संस्करण के संस्करण भी -iएक फ़ाइल को संपादित करने के विकल्प का समर्थन करते हैं जो आपने स्पष्ट रूप से कहा है कि आप नहीं चाहते हैं: वे एक अस्थायी फ़ाइल पर लिखते हैं और फिर फ़ाइल का नाम बदलते हैं। लेकिन शायद आप सिर्फ उपयोग कर सकते हैं ed। उदाहरण के लिए, फ़ाइल में होने वाली सभी घटनाओं को बदलने के fooलिए , आप यह कर सकते हैं:barfile.txt

echo ',s/foo/bar/g; w' | tr \; '\012' | ed -s file.txt

सिंटेक्स के समान है sed, लेकिन निश्चित रूप से बिल्कुल समान नहीं है।

लेकिन शायद आपको इस बात पर विचार करना चाहिए कि आप एक नामांकित अस्थायी फ़ाइल का उपयोग क्यों नहीं करना चाहते। यहां तक ​​कि अगर आपके पास एक -iसहायक नहीं है sed, तो आप आसानी से आपके लिए काम करने के लिए एक स्क्रिप्ट लिख सकते हैं। इसके बजाय sed -i 's/foo/bar/g' file, आप कर सकते थे inline file sed 's/foo/bar/g'। ऐसी पटकथा लिखने के लिए तुच्छ है। उदाहरण के लिए:

#!/bin/sh -e
IN=$1
shift
trap 'rm -f $tmp' 0
tmp=$( mktemp )
<$IN "$@" >$tmp && cat $tmp > $IN  # preserve hard links

अधिकांश उपयोगों के लिए पर्याप्त होना चाहिए।


1
उदाहरण के लिए, आप इस स्क्रिप्ट का नाम कैसे देंगे और आप इसे कैसे कहेंगे?
उभयचर

2
मैं इसे कॉल करूंगा inlineऔर इसे ऊपर वर्णित के रूप में आमंत्रित करूंगा :inline inputfile sed 's/foo/bar/g'
विलियम पर्ससेल

1
वाह, edकेवल जवाब है कि वास्तव में जगह में करता है। मैंने कभी जरूरत पहली बार ed। धन्यवाद। थोड़ा अनुकूलन उपयोग करना है echo -e ",s/foo/bar/g\012 w"या echo $',s/foo/bar/g\012 w'जहां शेल इसे अतिरिक्त trकॉल से बचने की अनुमति देता है ।
अकोस्टैडिनोव

2
edवास्तव में संशोधनों को इन-प्लेस नहीं करता है। से straceउत्पादन, जीएनयू edएक अस्थायी फ़ाइल बनाता है, अस्थायी फ़ाइल में परिवर्तन लिखते हैं, तो पूरे मूल फ़ाइल पुनर्लेखन करता है, हार्ड लिंक संरक्षण। से trussउत्पादन, सोलारिस 11 edभी एक अस्थायी फ़ाइल का उपयोग करता है, लेकिन साथ बचत पर मूल फ़ाइल नाम के अस्थायी फ़ाइल का नाम बदलता wआदेश, किसी भी हार्ड लिंक को नष्ट करने।
एंड्रयू हेनले

@AndrewHenle यह हतोत्साहित करने वाला है। edकि वर्तमान MacOS (मोजावे, जो कुछ भी है कि विपणन शब्दजाल साधन) के साथ जहाजों अभी भी hardlinks बरकरार रखता है। YMMV
विलियम पार्सल

10

आप vi का उपयोग कर सकते हैं

vi -c '%s/foo/bar/g' my.txt -c 'wq'

9

sed का समर्थन करता है यथा-स्थान संपादन। से man sed:

-i[SUFFIX], --in-place[=SUFFIX]

    edit files in place (makes backup if extension supplied)

उदाहरण :

मान लें कि आपके पास hello.txtपाठ के साथ एक फ़ाइल है :

hello world!

यदि आप पुरानी फ़ाइल का बैकअप रखना चाहते हैं, तो उपयोग करें:

sed -i.bak 's/hello/bonjour' hello.txt

आप दो फ़ाइलों के साथ समाप्त होंगे: hello.txtसामग्री के साथ:

bonjour world!

और hello.txt.bakपुरानी सामग्री के साथ।

यदि आप एक प्रति नहीं रखना चाहते हैं, तो बस एक्सटेंशन पैरामीटर पास न करें।


3
ओपी ने विशेष रूप से उल्लेख किया है कि उनका मंच इस (लोकप्रिय लेकिन) अमानक विकल्प का समर्थन नहीं करता है।
ट्रिपलए

3

आपने निर्दिष्ट नहीं किया कि आप किस शेल का उपयोग कर रहे हैं, लेकिन zsh के साथ आप =( )इसे प्राप्त करने के लिए निर्माण का उपयोग कर सकते हैं । की तर्ज पर कुछ:

cp =(sed ... file; sync) file

=( )के समान है, >( )लेकिन एक अस्थायी फ़ाइल बनाता है जो cpसमाप्त होने पर स्वचालित रूप से हटा दी जाती है।


3
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt

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


3

यदि आप वर्णों की समान मात्रा की जगह ले रहे हैं और ध्यान से "इन-प्लेस" फाइलों के संपादन के बाद ...

<>फ़ाइल को पढ़ने और लिखने के लिए खोलने के लिए आप पुनर्निर्देशन ऑपरेटर का भी उपयोग कर सकते हैं :

sed 's/foo/bar/g' file 1<> file

इसे लाइव देखें:

$ cat file
hello
i am here                           # see "here"
$ sed 's/here/away/' file 1<> file  # Run the `sed` command
$ cat file
hello
i am away                           # this line is changed now

से पढ़ना और लेखन के लिए बैश संदर्भ मैनुअल → 3.6.10 उद्घाटन फ़ाइल वर्णनकर्ता :

पुनर्निर्देशन ऑपरेटर

[n]<>word

फ़ाइल जिसका नाम फ़ाइल डिस्क्रिप्टर n पर पढ़ने और लिखने दोनों के लिए खोला जाने वाला शब्द का विस्तार है, या यदि एन निर्दिष्ट नहीं है, तो फ़ाइल डिस्क्रिप्टर 0 पर। यदि फ़ाइल मौजूद नहीं है, तो यह बनाई गई है।


यह फ़ाइल द्वारा दूषित है। मैं इसके पीछे के कारण के बारे में निश्चित नहीं हूं। paste.fedoraproject.org/462017
जे वानी

पंक्तियाँ देखें [43-44], [88-89], [135-136]
जे वानी

2
यह ब्लॉगपोस्ट बताता है कि इस उत्तर का उपयोग क्यों नहीं किया जाना चाहिए। backreference.org/2011/01/29/in-place-editing-of-files
नेहल जे वानी

@NehalJWani मैं लेख के लिए एक लंबा पढ़ा होगा, सिर के लिए धन्यवाद! मैंने उत्तर में जो उल्लेख नहीं किया है, वह यह है कि यदि यह समान मात्रा में वर्ण बदलता है तो यह काम करता है।
फेडोरक्वी 'SO रोकना नुकसानदायक'

@NehalJWani यह कहा जा रहा है, मुझे खेद है अगर मेरे जवाब से आपकी फाइलों पर नुकसान हुआ। आपके द्वारा दिए गए लिंक को पढ़ने के बाद मैं इसे सुधार (या यदि आवश्यक हो तो हटा दें) के साथ अपडेट करूंगा।
फेडोरक्वी 'एसओ

2

जैसे कि मोनेपनी ने स्काईफॉल में कहा: "कभी-कभी पुराने तरीके सबसे अच्छे होते हैं।" किंकेड ने बाद में भी कुछ ऐसा ही कहा।

$ printf ',s/false/true/g\nw\n' | ed {YourFileHere}

जगह-जगह खुश संपादन। फ़ाइल लिखने के लिए '\ nw \ n' जोड़ा गया। अनुरोध का जवाब देने में देरी के लिए माफी।


क्या आप बता सकते हैं कि यह क्या करता है?
मैट मोंटेग

1
यह एड (1), टेक्स्ट एडिटर को स्टड के लिए लिखे गए कुछ पात्रों के साथ आमंत्रित करता है। 30 वर्ष से कम आयु के व्यक्ति के रूप में, मुझे लगता है कि मेरे लिए यह कहना ठीक है कि एड (1) डायनासोर के रूप में है क्योंकि डायनासोर हमारे लिए हैं। वैसे भी, एड खोलने और उस सामान को टाइप करने के बजाय, जेलेटिन उपयोग करने में पात्रों को पाइप कर रहा है |। @MattMontag
अरी स्वेडलर

यदि आप पूछ रहे हैं कि कमांड क्या करते हैं, तो उनमें से दो को समाप्त कर दिया गया है \n। [श्रेणी] s / <पुराना> / <नया> / <ध्वज> स्थानापन्न आदेश का रूप है - कई अन्य पाठ संपादकों में देखा गया एक प्रतिमान (ठीक है, विम, एड का एक सीधा वंश) वैसे भी, gध्वज खड़ा है "वैश्विक", और इसका अर्थ है "प्रत्येक पंक्ति पर प्रत्येक उदाहरण जिसे आप देखते हैं"। रेंज 3,53-5 पर दिखती है। ,5StartOfFile-5 को 3,देखता है, लाइनों 3-EndOfFile को ,देखता है और StartOfFile-EndOfFile को देखता है। हर लाइन पर एक वैश्विक सबस्टीट्यूट कमांड जो "असत्य" को "सही" के साथ बदलता है। उसके बाद, राइट कमांड, wदर्ज किया जाता है।
अरी स्वीडलर

1

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

find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.