मैक (BSD) और लिनक्स दोनों पर काम करने वाला फ्लैग इन-प्लेस फ्लैग


237

sedलिनक्स और मैक दोनों पर काम करने वाले बैकअप के बिना इन-टू-इन-प्लेस संपादन का एक आमंत्रण है ? जबकि बीएसडी sedओएस एक्स के साथ भेज दिया गया है sed -i '' …, जीएनयू sedलिनक्स वितरण आमतौर पर रिक्त इनपुट फ़ाइल नाम (बैकअप एक्सटेंशन के sed -i …बजाय ) के रूप में उद्धरण की व्याख्या के साथ आते हैं, और इसके बजाय की जरूरत है ।

क्या कोई कमांड लाइन सिंटैक्स है जो दोनों फ्लेवर के साथ काम करता है, इसलिए मैं दोनों सिस्टम पर एक ही स्क्रिप्ट का उपयोग कर सकता हूं?


क्या पर्ल एक विकल्प नहीं है? क्या आप sed का उपयोग करते हैं?
नौफल इब्राहिम

शायद GNU संस्करण स्थापित करें और इसका उपयोग करें! topbug.net/blog/2013/04/14/… ? मैं कोशिश करूँगा कि पहले। फिर में भी उस तरह का चूसता रहा।
दिमित्री मिंकोवस्की

2
@ दिदिमाधिमा: इस सवाल को ब्राउज़ करने वाले कुछ अन्य लोगों के लिए दिलचस्प हो सकता है जिनके पास व्यक्तिगत स्क्रिप्ट हैं जो उनके ओएस एक्स मशीन पर टूटती हैं। मेरे मामले में, हालांकि, मुझे एक ओपन सोर्स प्रोजेक्ट की बिल्ड सिस्टम के लिए इसकी आवश्यकता थी, जहां आपके उपयोगकर्ता को GNU सेड को स्थापित करने के लिए कहना सबसे पहले इस अभ्यास के मूल उद्देश्य को हराया होगा (कुछ फ़ाइलों को "हर जगह" काम करता है) फैशन ।
dnadlinger

@klickverbot हाँ, समझ में आता है। मैंने पहली बार टिप्पणी को एक उत्तर के रूप में जोड़ा, और फिर इसे हटा दिया, यह महसूस करते हुए कि यह आपके प्रश्न का उत्तर नहीं था :)।
दिमित्री मिंकोवस्की

1
क्रॉस संदर्भ: sed -i (इन-प्लेस एडिटिंग) के साथ पोर्टेबिलिटी कैसे प्राप्त करें? यूनिक्स और लिनक्स स्टैक एक्सचेंज पर।
एमवीजी

जवाबों:


212

यदि आप वास्तव में केवल sed -i'आसान' तरीके का उपयोग करना चाहते हैं , तो निम्नलिखित GNES और BSD / Mac दोनों पर काम करता है sed:

sed -i.bak 's/foo/bar/' filename

अंतरिक्ष और डॉट की कमी पर ध्यान दें।

सबूत:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

जाहिर है आप तब .bakफ़ाइलों को हटा सकते हैं।


2
जाने का यह रास्ता है। कुछ वर्ण जोड़ें, और यह पोर्टेबल है। बैकअप फ़ाइल को हटाना तुच्छ है (आपके पास पहले से ही फ़ाइलनाम है जब आह्वान किया जाता है sed)
slezica

यह मैक पर काम किया, लेकिन ubuntu 16.04 पर यह मूल फ़ाइल को 0 बाइट्स पर अधिलेखित कर देता है और .bak फ़ाइल को 0 बाइट्स के साथ भी बनाता है?
मकान

1
ध्यान दें, MacOS सिएरा पर (और संभवतः पहले, मैं एक मशीन काम नहीं है), sedएक स्थितीय को स्वीकार नहीं करता commandतर्क जब साथ आमंत्रण -iयह - चाहिए , एक और ध्वज के साथ आपूर्ति की जा -e। इस प्रकार, कमांड बन जाता है:sed -i.bak -e 's/foo/bar/' filename
ELLIOTTCABLE

5
यह बैकअप बनाता है, जबकि ओपी विशेष रूप से इन-प्लेस संपादन के लिए पूछता है।
मार्क-आंद्रे लाफ्यून

8
तो इसका पूरा उपाय है:sed -i.bak 's/foo/bar/' file && rm file.bak
joeytwiddle

112

यह GNU sed के साथ काम करता है, लेकिन OS X पर नहीं:

sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file

यह OS X पर काम करता है, लेकिन GNU sed के साथ नहीं:

sed -i '' -e 's/foo/bar/' target.file

ओएस एक्स पर आप

  • sed -i -eबैकअप फ़ाइल के एक्सटेंशन को सेट करने के बाद से उपयोग नहीं किया जा सकता है-e
  • sed -i'' -eएक ही कारण के लिए उपयोग नहीं कर सकते हैं - यह -iऔर के बीच एक जगह की जरूरत है ''

1
@AlexanderMills, sed को बताता है कि अगला तर्क एक आदेश है - यहां भी छोड़ दिया जा सकता है।
बेंजामिन डब्ल्यू।

4
ध्यान दें कि -iऔर -i''शेल पार्सिंग समय पर समान हैं; उन दो पहले आह्वान पर अलग-अलग व्यवहार sed नहीं कर सकते , क्योंकि यह ठीक उसी तरह के तर्क देता है।
21

44

जब OSX पर, मैं हमेशा स्क्रिप्ट्स में समस्याओं से बचने के लिए, Homebrew के माध्यम से GNU sed संस्करण स्थापित करता हूं, क्योंकि अधिकांश स्क्रिप्ट GNU sed संस्करणों के लिए लिखे गए थे।

brew install gnu-sed --with-default-names

फिर आपकी BSD sed को GNU sed से बदल दिया जाएगा।

वैकल्पिक रूप से, आप बिना डिफ़ॉल्ट नाम के स्थापित कर सकते हैं, लेकिन तब:

  • अपना बदलें PATHइंस्टॉल करने के बाद निर्देशानुसारgnu-sed
  • अपनी प्रणाली के बीच gsedया sedउसके आधार पर चुने जाने के लिए अपनी स्क्रिप्ट में जाँच करें

4
--with-default-namesथा homebrew कोर से हटा दिया , में और अधिक जानकारी के लिए इस सवाल का जवाब। जब स्थापित करने gnu-sedअब, स्थापना के निर्देश निर्दिष्ट करें कि आप जोड़ने की जरूरत है gnubinअपने को PATH:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
pgericson

18

जैसा कि नौफ़ल इब्राहिम पूछता है, आप पर्ल का उपयोग क्यों नहीं कर सकते? किसी भी मैक में पर्ल होगा, और बहुत कम लिनक्स या बीएसडी वितरण हैं जो आधार प्रणाली में पर्ल के कुछ संस्करण को शामिल नहीं करते हैं। केवल उन वातावरणों में से एक, जिनमें पर्ल की वास्तव में कमी हो सकती है, बिजीबॉक्स होगा (जो कि जीएनयू / लिनक्स की तरह काम करता है -i, सिवाय इसके कि कोई बैकअप एक्सटेंशन निर्दिष्ट नहीं किया जा सकता है)।

जैसा कि इस्माइल सिफारिश करता है,

चूँकि perl हर जगह उपलब्ध है, मैं बस करता हूँ perl -pi -e s,foo,bar,g target.file

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


मुझे यह समाधान पसंद है। perl1 मई, 2009 से लिनक्स स्टैंडर्ड बेस स्पेसिफिकेशन का एक हिस्सा है। refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/…
ऑरेगॉनट्रैल

1
यह आसानी से पोर्टेबिलिटी के लिए सबसे अच्छा समाधान है
इकनप्सनाई

17

यह काम करने का कोई तरीका नहीं है।

एक तरीका अस्थायी फ़ाइल का उपयोग करना है:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e "s/abc/def/" some/file > $TMP_FILE
mv $TMP_FILE some/file

यह दोनों पर काम करता है


क्या कोई कारण है कि SOME_FILE = "$ (sed -s" s / abc / def / "some / file)"; इको "$ SOME_FILE"> कुछ / फ़ाइल; इसके बजाय काम नहीं करेगा
जेसन सकल

लगता है कि आप एक बैश चर के अधिकतम आकार तक सीमित होंगे, नहीं? सुनिश्चित नहीं है कि यह GBs फ़ाइलों के साथ काम करेगा।
एनालॉग

3
यदि आप एक अस्थायी फ़ाइल बना रहे हैं, तो नीचे दिए गए @kine सुझाव के अनुसार बैकअप फ़ाइल बनाने के लिए एक्सटेंशन क्यों नहीं दें (जिसे आप तब हटा सकते हैं)?
एलेक्स डुप्यू

13

उत्तर: नहीं।

मूल रूप से स्वीकृत उत्तर वास्तव में वह नहीं करता है जो अनुरोध किया जाता है (जैसा कि टिप्पणियों में उल्लेख किया गया है)। (मुझे इसका जवाब तब मिला जब कारण की तलाश थीfile-e मेरे निर्देशिका में "बेतरतीब ढंग से" दिखाई देने वाले थी।)

sed -iमैकओएस और लिंज़ दोनों पर लगातार काम करने का कोई रास्ता नहीं है ।

मेरी सिफारिश, जो इसके लायक है, वह sed(जिसमें जटिल विफलता मोड हैं) के साथ इन-प्लेस को अपडेट नहीं करना है , बल्कि नई फाइलें उत्पन्न करना और बाद में उनका नाम बदलना है। दूसरे शब्दों में: से बचें -i


9

-iविकल्प का हिस्सा नहीं है POSIX Sed । V मोड में Vim का उपयोग करने के लिए एक अधिक पोर्टेबल विधि होगी:

ex -sc '%s/alfa/bravo/|x' file
  1. % सभी लाइनों का चयन करें

  2. s बदलने के

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


यह सही जवाब है। POSIX की एक प्रमुख विशेषता पोर्टेबिलिटी है।
काजुकेनबो

9

यहाँ एक और संस्करण है जो बिना evalबैकअप फाइल को डिलीट किए बिना लिनक्स और मैकओएस पर काम करता है । यह sedमापदंडों को संग्रहीत करने के लिए बैश सरणियों का उपयोग करता है , जो उपयोग करने की तुलना में क्लीनर है eval:

# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
  # For macOS, use two parameters
  Darwin*) sedi=(-i "")
esac

# Expand the parameters in the actual call to "sed"
sed "${sedi[@]}" -e 's/foo/bar/' target.file

यह न तो बैकअप फाइल बनाता है, न ही एप्लाइड कोट्स वाली फाइल।


2
यह सही जवाब है। मैं इसे थोड़ा सरल करूंगा, लेकिन यह विचार पूरी तरह से काम करता है sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '') sed "${sedi[@]}" -e 's/foo/bar/' target.file
एलेक्स स्क्रीपनीक

अच्छी चीज़! मैं पठनीयता के लिए लंबा संस्करण पसंद करता हूं, हालांकि।
nwinkler

1
मेरे लिए अलग-अलग प्रणाली के साथ संगत होने का यह सबसे अच्छा तरीका है।
विक्टर चो

6

स्टीव पॉवेल का जवाब काफी सही है, OSX और लिनक्स (Ubuntu 12.04) पर sed के लिए MAN पृष्ठ से परामर्श करना दो ऑपरेटिंग सिस्टम में 'इन-प्लेस' सेड के उपयोग के भीतर अनुकूलता पर प्रकाश डालता है।

JFYI, -i और किसी भी उद्धरण के बीच कोई स्थान नहीं होना चाहिए (जो खाली फ़ाइल एक्सटेंशन को दर्शाता है) इस प्रकार से लिनक्स के लिनक्स संस्करण का उपयोग करना

sed लिनक्स मैन पेज

#Linux
sed -i"" 

तथा

sed OSX मैन पेज

#OSX (notice the space after the '-i' argument)
sed -i "" 

मैंने इसे एक स्क्रिप्ट में एक उपनाम कमांड का उपयोग करके और एक bash 'if' के भीतर ' uname ' के OS-name आउटपुट का उपयोग करके प्राप्त किया । ओएस-डिपेंडेंट कमांड स्ट्रिंग्स को वेरिएबल्स में स्टोर करने की कोशिश की गई और उद्धरणों की व्याख्या करते समय याद किया गया। 'का उपयोग shopt -s expand_aliases ' आदेश का विस्तार / उपनाम अपनी स्क्रिप्ट में परिभाषित का उपयोग करने के लिए आवश्यक है। दुकान का उपयोग यहाँ से निपटा है


1

यदि आपको sedकिसी bashस्क्रिप्ट में इन-प्लेस करने की आवश्यकता है, और आप .bkp फ़ाइलों के साथ परिणाम के लिए इन-प्लेस नहीं चाहते हैं, और आपके पास ओएस का पता लगाने का एक तरीका है (जैसे, ostype.sh का उपयोग करके ), - तब bashनिर्मित में evalकाम करना चाहिए के साथ निम्नलिखित हैक :

OSTYPE="$(bash ostype.sh)"

cat > myfile.txt <<"EOF"
1111
2222
EOF

if [ "$OSTYPE" == "osx" ]; then
  ISED='-i ""'
else # $OSTYPE == linux64
  ISED='-i""'
fi

eval sed $ISED 's/2222/bbbb/g' myfile.txt
ls 
# GNU and OSX: still only myfile.txt there

cat myfile.txt
# GNU and OSX: both print:
# 1111
# bbbb

# NOTE: 
# if you just use `sed $ISED 's/2222/bbbb/g' myfile.txt` without `eval`,
# then you will get a backup file with quotations in the file name, 
# - that is, `myfile.txt""`

0

आप स्पंज का उपयोग कर सकते हैं। स्पंज एक पुराना यूनिक्स प्रोग्राम है, जो कि म्यूटिल पैकेज (उबंटू और शायद डेबियन, और होमब्रे में मैक में) में पाया जाता है।

यह पाइप से सभी सामग्री को बफर करेगा, पाइप के करीब होने तक प्रतीक्षा करें (शायद इसका मतलब है कि इनपुट फ़ाइल पहले से ही करीब है) और फिर लिख दें:

से आदमी पेज :

सार

sed '...' फ़ाइल | grep '...' | स्पंज फ़ाइल


3
अच्छा दृष्टिकोण - दुर्भाग्य से वास्तव में मूल स्थिति में मदद नहीं करता है क्योंकि sed का सहारा लेने का कारण ग्राहक मशीनों पर उपयोग किए जाने वाले क्रॉस-प्लेटफॉर्म हेल्पर स्क्रिप्ट में उपयोग करने के लिए कुछ होना चाहिए, जहां आप कुछ और पर निर्भर नहीं कर सकते हैं, लेकिन सिस्टम उपकरण लगाए जा रहे हैं। हालांकि किसी और के लिए उपयोगी हो सकता है।
dnadlinger 17

0

लिनक्स और ओएस एक्स पर मेरे लिए निम्नलिखित काम करता है:

sed -i' ' <expr> <file>

एक फ़ाइल fयुक्त के लिए जैसेaaabbaaba

sed -i' ' 's/b/c/g' f

aaaccaacaलिनक्स और मैक दोनों पर पैदावार । ध्यान दें कि एक उद्धृत स्ट्रिंग है जिसमें एक स्थान है , जिसमें और स्ट्रिंग के बीच कोई स्थान नहीं है-i । सिंगल या डबल कोट्स दोनों काम करते हैं।

लिनक्स पर मैं bashउबंटू 14.04.4 के तहत और 4.3 संस्करण पर OS X 10.11.4 El Capitan (डार्विन 15.4.0) के तहत संस्करण 4.3.11 का उपयोग कर रहा हूं ।


1
वाह, मुझे खुशी है कि मैंने उपरोक्त सभी को यह कहते हुए नहीं सुना कि यह असंभव था और पढ़ता रहा! यह वास्तव में सिर्फ काम करता है। धन्यवाद!
कार्मिक

4
मैक ओएस पर मेरे लिए काम नहीं करता है ... फ़ाइल नाम के अंत में संलग्न अंतरिक्ष के साथ नई फ़ाइल बनाई गई है
Frédéric

मैक पर मेरे लिए काम नहीं करता है (/ usr / bin / sed) - मेरे पास अब एक अतिरिक्त बैकअप फ़ाइल है जिसमें फ़ाइल नाम में संलग्न स्थान है :-(
paul_h

सिंगल कोट्स में से स्पेस लेने की कोशिश करें, यह मेरे लिए काम करता है।
डीपीएस

0

मैं इस समस्या में भाग गया। एकमात्र त्वरित समाधान मैक में sed को ग्नू संस्करण में बदलना था:

brew install gnu-sed

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