मैक OSX और अन्य "मानक" sed पर sed के बीच अंतर?


61

इस साइट पर दिए गए उत्तर का उपयोग करने के लिए मुझे इस मुद्दे के लिए एक सीड कमांड के बारे में एक प्रश्न का उपयोग करने में कुछ समस्याएँ आ रही हैं, दो अन्य पंक्तियों की सामग्री के साथ एक रिक्त पंक्ति को बदलने के लिए , और इसे लाया गया था यदि मैक ओएस पर sed कमांड (10.6.7 मेरे लिए) ) फरक है। मुझे नहीं लगता कि यह है, लेकिन सोच रहा था कि क्या इस साइट पर दूसरों ने अलग तरीके से सोचा।

जवाबों:


43

यूनिक्स वेरिएंट के बीच शेल उपयोगिताओं का व्यवहार मामूली तरीकों से भिन्न होता है। एक जटिल इतिहास के साथ कई यूनिक्स संस्करण हैं । POSIX मानक और इसके सुपरसेट एकल UNIX विनिर्देशन जैसे मानकीकरण प्रयास हैं । आजकल अधिकांश प्रणालियाँ POSIX: 2001 को लागू करती हैं, जिसे एकल विचलन विशिष्टता संस्करण 3 के रूप में भी जाना जाता है , जिसमें मामूली विचलन और कई एक्सटेंशन हैं। एकल यूनिक्स विनिर्देश एक ट्यूटोरियल नहीं है, लेकिन संस्करण 3 पठनीय है यदि आपको पहले से ही पता है कि एक कमांड क्या कर रहा है। आप यह जानने के लिए परामर्श कर सकते हैं कि कुछ सुविधा मानक है या किसी विशेष प्रणाली का विस्तार है।

अधिकांश यूनिक्स उपयोगकर्ता लिनक्स का उपयोग करते हैं और किसी अन्य संस्करण का उपयोग नहीं करते हैं। लिनक्स GNU उपयोगिताओं के साथ आता है , जिसमें अक्सर मानक के कई एक्सटेंशन होते हैं। तो आपको वहां बहुत सारे कोड मिल जाएंगे जो लिनक्स पर काम करते हैं लेकिन अन्य यूनियनों पर नहीं, क्योंकि यह उन एक्सटेंशन पर निर्भर करता है।

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

जीएनयू सेड में गैर-मानक एक्सटेंशन में से एक एक साथ चलने वाले कई कमांड का समर्थन कर रहा है। उदाहरण के लिए, यह GNU sed प्रोग्राम में सभी लाइनों को प्रिंट करता है a, लेकिन पहले bमें बदल जाता है c:

sed -ne '/a/ {s/b/c/g; p}'

{और }वास्तव में अलग-अलग कमांड हैं, इसलिए पूर्ण पोर्टेबिलिटी के लिए, आपको उन्हें अलग-अलग लाइनों (एक फ़ाइल में) या अलग-अलग -eतर्क (कमांड लाइन पर) में निर्दिष्ट करने की आवश्यकता है । कमांड विभाजक की कमी के बाद {और कमांड विभाजक के ;रूप में उपयोग आम एक्सटेंशन हैं। पहले एक कमांड विभाजक की कमी }एक कम सामान्य विस्तार है। यह मानक-अनुपालन है:

sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'

यह अमानक है, लेकिन आमतौर पर स्वीकार किया जाता है:

sed -ne '/a/ { s/b/c/g; p; }'

एक और अमानक लेकिन सामान्य विस्तार \nएक sप्रतिस्थापन पाठ में एक नई लाइन का उपयोग करने के लिए है (एक regexp में उपयोग मानक है)। पोर्टेबल विधि में बैकस्लैश-न्यूलाइन को सीड स्क्रिप्ट में शामिल करना है। एक और सामान्य विस्तार है \+, \?और \|regexps में एक या एक से अधिक का मतलब है, एक और प्रत्यावर्तन; पोर्टेबल बेसिक रेगुलर एक्सप्रेशन में इनमें से कुछ भी नहीं है। उदाहरण के लिए, पहला कमांड व्हाट्सएप के सन्निहित अनुक्रमों को एक नई पंक्ति द्वारा प्रतिस्थापित करने का एक गैर-पोर्टेबल तरीका है; दूसरा आदेश एक मानक-अनुरूप समकक्ष है।

sed -e 's/ \+/\n/'
sed -e 's/  */\
/'

ध्यान दें कि GNU एक्सटेंशन के बारे में उन सभी मामलों में, यह वह उपयोग है जो गैर-मानक है। GNU sedअपने आप में आज्ञाकारी है क्योंकि यह मानक द्वारा अनुमत चीजों (लेकिन आवश्यक नहीं, अनिर्दिष्ट) को करता है। ऐसे मामले हैं जहां यह अनुपालन नहीं है और जहां इसे POSIXLY_CORRECTपर्यावरण में चलाने से मदद मिल सकती है। इसके साथ ही s/[\n]//gबैकलैश और nकैरेक्टर्स को हटा देना चाहिए, लेकिन इसके बजाय नए सिरे को हटा दें। या Nअंतिम पंक्ति पर कमांड का व्यवहार ।
स्टीफन चेज़लस

sed -ne '/a/ { s/b/c/g; p; }'मानक के 2016 संस्करण के बाद से मानक है। यह हमेशा पोर्टेबल था। देखें austingroupbugs.net/view.php?id=944&nbn=7
स्टीफन Chazelas

60

OS X वर्तमान में 2005 से FreeBSD sed के साथ आता है। नीचे दिए गए अधिकांश अंतर अन्य BSD sed संस्करणों पर भी लागू होते हैं।

-EERE और GNU सेड के उपयोग के लिए OS X का sed उपयोग करता है -r। GNU sed के -Eलिए एक उपनाम है -r(4.2 में जोड़ा गया, 4.3 तक प्रलेखित नहीं)। FreeBSD और NetBSD के नए संस्करणों ने sed दोनों का समर्थन किया -Eऔर -r। OpenBSD sed केवल समर्थन करता है -E

-i ''OS X के सेड के साथ काम करता है लेकिन GNU सेड के साथ नहीं। -iGNU sed के साथ काम करता है, NetBSD, OpenBSD के हाल के संस्करण sed, लेकिन OS X का sed नहीं। -i -eदोनों के साथ काम करता है, लेकिन FreeBSD के मामले में sedमूल -eफ़ाइल का नाम फ़ाइल नाम के साथ जोड़ा गया है (और आपको एक से अधिक एक्सप्रेशन पास करने की आवश्यकता नहीं है sed) का बैकअप बनाता है ।

जीएनयू sed की व्याख्या की तरह दृश्यों से बचने \t, \n, \001, \x01, \w, और \b। OS X की sed और POSIX sed केवल व्याख्या करते हैं \n(लेकिन प्रतिस्थापन भाग में नहीं s)।

GNU sed व्याख्या करता है \|, \+और \?BRE में लेकिन OS X का sed और POSIX sed नहीं। \(, \), \{, और \}POSIX BRE हैं।

GNU sed ;पहले }ओएस एक्स के सेड को छोड़ने या छोड़ने की अनुमति नहीं देता है।

i(सम्मिलित करें), a(परिशिष्ट), और c(परिवर्तन) के बाद बैकस्लैश और ओएस एक्स के सेड और पोसिक्स सेड में एक नई रेखा का पालन करना होगा लेकिन जीएनयू सेड में नहीं। जीएनयू एसईडी पाठ द्वारा डाला के बाद एक लापता न्यू लाइन कहते हैं i, aया cलेकिन ओएस एक्स के sed नहीं करता है। उदाहरण के लिए sed 1iaएक GNU विकल्प है sed $'1i\\\na\n'

उदाहरण के लिए printf a|sed -n p, OS X के सेड में एक नई पंक्ति जोड़ता है लेकिन GNU सेड में नहीं।

OS X का सेड Iकेस (असंवेदनशील) या M(बहु-पंक्ति) संशोधक का समर्थन नहीं करता है । FreeBSD sed समर्थन के नए संस्करण I

OS X का sed समर्थन नहीं करता है -s( --separate), -u( --unbuffered), या -z( --null-data)।

एक बीएसडी विकल्प जो जीएनयू सेड द्वारा समर्थित नहीं है -a, जो wकिसी फाइल को रौंदने के बजाय एक फाइल में जोड़ देता है ।

GNU sed कमांड के उदाहरण जो OS X के सेड के साथ काम नहीं करते हैं:

sed /pattern/,+2d # like `sed '/pattern/{N;N;d;}'`
sed -n 0~3p # like `awk NR%3==0`
sed /pattern/Q # like `awk '/pattern/{exit}1'` or `sed -n '/pattern/,$!p'`
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a shell command
sed -n l0 # 0 disables wrapping

4
-i -eOSX पर काम नहीं करता है। यह -eप्रत्यय के रूप में परस्पर जुड़ता है ।
क्रिस मार्टिन

3
@ क्रिसमार्टिन हाँ, ओएस एक्स संस्करण में -iहमेशा एक प्रत्यय की आवश्यकता होती है, भले ही एक खाली स्ट्रिंग हो। इसलिए -i '' -eकाम करना चाहिए।
वाल्ड्रिऑस

@waldyrious यह केवल OSX पर काम करता है।
क्रिस मार्टिन

हाँ, यह उस संस्करण का एक
अंश है

3
वाक्य " -i -eदोनों के साथ काम करता है।" आपके जवाब से पता चलता है कि एक क्रॉस-प्लेटफॉर्म समाधान है। जाहिरा तौर पर वहाँ नहीं है।

5

सबसे अच्छा तरीका है कि मैंने लिनक्स और मैक दोनों पर समान स्क्रिप्ट का काम किया है:

sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
  rm -- "${TARGET}.bak"

या perlजहां -iसे आता है उसका उपयोग करें । perl -Tpi -e 's/foo/bar/' -- "$TARGET"
स्टीफन चेजालस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.