असल में, यह एक पोर्टेबिलिटी (और विश्वसनीयता) मुद्दा है।
प्रारंभ में, echoकिसी भी विकल्प को स्वीकार नहीं किया और किसी भी चीज़ का विस्तार नहीं किया। यह सब एक अंतरिक्ष चरित्र द्वारा अलग किए गए अपने तर्कों को आउटपुट कर रहा था और एक नए चरित्र द्वारा समाप्त किया गया था।
अब, किसी ने सोचा कि अच्छा होगा अगर हम echo "\n\t"न्यूलाइन या टैब कैरेक्टर को आउटपुट करना पसंद कर सकते हैं या आपके पास ट्रेंडिंग न्यूलाइन कैरेक्टर को आउटपुट नहीं करने का विकल्प है।
उन्होंने तब कठिन सोचा, लेकिन उस कार्यक्षमता को शेल में जोड़ने के बजाय ( perlजहां दोहरे उद्धरण के अंदर, \tवास्तव में एक टैब वर्ण का मतलब है), उन्होंने इसे जोड़ा echo।
डेविड कॉर्न गलती का एहसास और खोल उद्धरण का एक नया रूप पेश किया: $'...'जो बाद से कॉपी किया गया था bashऔर zshलेकिन यह अभी तक भी उस समय तक देर हो चुकी थी।
अब जब एक मानक यूनिक्स echoएक तर्क प्राप्त करता है जिसमें दो वर्ण होते हैं \और t, उन्हें आउटपुट करने के बजाय, यह एक टैब वर्ण को आउटपुट करता है। और जैसे ही यह \cएक तर्क में देखता है, यह आउटपुट करना बंद कर देता है (इसलिए अनुगामी न्यूलाइन आउटपुट भी नहीं है)।
अन्य गोले / यूनिक्स विक्रेताओं / संस्करणों ने इसे अलग तरीके से करने के लिए चुना: उन्होंने -eभागने के दृश्यों का विस्तार करने के लिए एक विकल्प जोड़ा , और -nअनुगामी न्यूलाइन का उत्पादन नहीं करने का एक विकल्प। कुछ के पास -Eएस्केप सीक्वेंस को डिसेबल करने के लिए है, कुछ के पास -nनहीं है -e, लेकिन एग्जीक्यूटिव द्वारा सपोर्ट किए गए एग्जिट सीक्वेंस की लिस्ट echoजरूरी नहीं है कि दूसरे से सपोर्ट हो।
स्वेन मस्कच के पास एक अच्छा पृष्ठ है जो समस्या की सीमा दिखाता है ।
उन echoकार्यान्वयनों पर, जो विकल्पों का समर्थन करते हैं, आम तौर पर --विकल्पों के अंत को चिह्नित करने के लिए कोई समर्थन नहीं होता है ( echoकुछ गैर-बॉर्न जैसे शेल का निर्माण होता है, और इसके -लिए zsh समर्थन करता है ), इसलिए, उदाहरण के लिए, इसके "-n"साथ आउटपुट करना मुश्किल echoहै कई गोले।
जैसे कुछ गोले पर bash¹ या ksh93² या yash( $ECHO_STYLEचर), व्यवहार भी कैसे खोल संकलित किया गया था या पर्यावरण (जीएनयू पर निर्भर करता है echoके व्यवहार भी करता है, तो बदल जाएगा $POSIXLY_CORRECTवातावरण में और संस्करण के साथ है 4 , zsh'इसके साथ रों bsd_echoविकल्प, उनके posixविकल्प के साथ कुछ pdksh- आधारित या चाहे वे कहा जाए shया नहीं)। तो दो bash echoएस, एक ही संस्करण से भी एक ही bashव्यवहार करने की गारंटी नहीं है।
POSIX कहता है: यदि पहला तर्क है -nया किसी भी तर्क में बैकस्लैश हैं, तो व्यवहार अनिर्दिष्ट है । bashउस संबंध में गूंज POSIX नहीं है कि उदाहरण के लिए POSIX की आवश्यकता के रूप में echo -eआउटपुट नहीं है -e<newline>। UNIX विनिर्देश सख्त है, यह निषिद्ध करता है -nऔर \cआउटपुट को रोकने के लिए कुछ एस्केप दृश्यों के विस्तार की आवश्यकता होती है ।
उन विशिष्टताओं को वास्तव में यहां बचाव नहीं आता है, क्योंकि कई कार्यान्वयन अनुपालन नहीं करते हैं। यहाँ तक कि कुछ प्रमाणित प्रणालियाँ जैसे macOS 5 अनुपालन योग्य नहीं हैं।
वर्तमान वास्तविकता का वास्तव में प्रतिनिधित्व करने के लिए, POSIX को वास्तव में कहना चाहिए : यदि पहला तर्क ^-([eEn]*|-help|-version)$विस्तारित regexp से मेल खाता है या किसी भी तर्क में बैकस्लैश (या वर्ण जिनके एन्कोडिंग में αBIGL charset का उपयोग करने वाले स्थानों में बैकस्लैश वर्ण के एन्कोडिंग शामिल हैं ) हैं, तो व्यवहार है अनिर्दिष्ट।
सब सब में, आप नहीं जानते कि क्या echo "$var"उत्पादन होगा जब तक आप यह सुनिश्चित नहीं कर सकते कि $varइसमें बैकलैश वर्ण नहीं हैं और इसके साथ शुरू नहीं होता है -। POSIX विनिर्देश वास्तव में हमें printfउस मामले में इसके बजाय उपयोग करने के लिए कहता है ।
तो इसका क्या मतलब है कि आप echoअनियंत्रित डेटा को प्रदर्शित करने के लिए उपयोग नहीं कर सकते हैं । दूसरे शब्दों में, यदि आप एक स्क्रिप्ट लिख रहे हैं और यह बाहरी इनपुट ले रहा है (उपयोगकर्ता से तर्क के रूप में, या फ़ाइल सिस्टम से फ़ाइल नाम ...), तो आप echoइसे प्रदर्शित करने के लिए उपयोग नहीं कर सकते ।
यह ठीक है:
echo >&2 Invalid file.
यह नहीं है:
echo >&2 "Invalid file: $file"
(हालांकि यह कुछ (गैर UNIX अनुरूप) echoकार्यान्वयन के साथ ठीक काम करेगा bashजब xpg_echoविकल्प एक तरह से या किसी अन्य संकलन समय पर या पर्यावरण के माध्यम से सक्षम नहीं किया गया है)।
file=$(echo "$var" | tr ' ' _)अधिकांश क्रियान्वयनों में ठीक नहीं है (अपवादों के yashसाथ ECHO_STYLE=raw(कैविएट के साथ जो कि yashचर चर के मनमाने ढंग से अनुक्रम नहीं रख सकते हैं इसलिए मनमाने ढंग से फ़ाइल नाम नहीं) और zsh' echo -E - "$var"6 ' ।
printfदूसरी ओर, अधिक विश्वसनीय है, कम से कम जब यह मूल उपयोग तक सीमित है echo।
printf '%s\n' "$var"
$varकिसी भी वर्ण द्वारा इसकी विशेषता के बिना एक नई वर्ण विशेषता के बाद सामग्री का उत्पादन करेगा ।
printf '%s' "$var"
अनुगामी न्यूलाइन वर्ण के बिना इसका उत्पादन करेगा।
अब, printfकार्यान्वयन के बीच भी अंतर हैं । सुविधाओं का एक कोर है जो POSIX द्वारा निर्दिष्ट किया गया है, लेकिन फिर बहुत सारे एक्सटेंशन हैं। उदाहरण के लिए, कुछ %qतर्क को उद्धृत करने के लिए समर्थन करते हैं लेकिन यह कैसे किया जाता है यह शेल से शेल में भिन्न होता है, \uxxxxयूनिकोड वर्णों के लिए कुछ समर्थन । printf '%10s\n' "$var"बहु-बाइट स्थानों में व्यवहार भिन्न होता है , इसके लिए कम से कम तीन अलग-अलग परिणाम होते हैंprintf %b '\123'
लेकिन अंत में, यदि आप POSIX सुविधा के सेट से चिपके रहते हैं printfऔर इसके साथ बहुत अधिक फैंसी करने की कोशिश नहीं करते हैं, तो आप परेशानी से बाहर हैं।
लेकिन याद रखें कि पहला तर्क प्रारूप है, इसलिए इसमें चर / अनियंत्रित डेटा नहीं होना चाहिए।
एक और अधिक विश्वसनीय echoका उपयोग करके कार्यान्वित किया जा सकता है printf, जैसे:
echo() ( # subshell for local scope for $IFS
IFS=" " # needed for "$*"
printf '%s\n' "$*"
)
echo_n() (
IFS=" "
printf %s "$*"
)
echo_e() (
IFS=" "
printf '%b\n' "$*"
)
उपधारा (जो अधिकांश शेल कार्यान्वयनों में एक अतिरिक्त प्रक्रिया को पैदा करता है) को local IFSकई गोले के साथ उपयोग करके या इसे इस तरह लिखकर टाला जा सकता है :
echo() {
if [ "$#" -gt 0 ]; then
printf %s "$1"
shift
fi
if [ "$#" -gt 0 ]; then
printf ' %s' "$@"
fi
printf '\n'
}
टिप्पणियाँ
1. कैसे bashके echoव्यवहार बदला जा सकता है।
bashसमय के साथ , दो चीजें हैं जो व्यवहार को नियंत्रित करती हैं echo( एक फ़ंक्शन या उपनाम के रूप में बगल में enable -n echoया फिर से परिभाषित करना echo): xpg_echo bashविकल्प और क्या bashपॉज़िक्स मोड में है। posixमोड को सक्षम किया जा सकता है अगर bashइसे पर्यावरण में या विकल्प के रूप में कहा जाता है shया :POSIXLY_CORRECTposix
अधिकांश प्रणालियों पर डिफ़ॉल्ट व्यवहार:
$ bash -c 'echo -n "\0101"'
\0101% # the % here denotes the absence of newline character
xpg_echo यूनिक्स की आवश्यकता के अनुसार दृश्यों का विस्तार:
$ BASHOPTS=xpg_echo bash -c 'echo "\0101"'
A
यह अभी भी सम्मान -nऔर -e(और -E):
$ BASHOPTS=xpg_echo bash -c 'echo -n "\0101"'
A%
साथ xpg_echoऔर POSIX मोड:
$ env BASHOPTS=xpg_echo POSIXLY_CORRECT=1 bash -c 'echo -n "\0101"'
-n A
$ env BASHOPTS=xpg_echo sh -c 'echo -n "\0101"' # (where sh is a symlink to bash)
-n A
$ env BASHOPTS=xpg_echo SHELLOPTS=posix bash -c 'echo -n "\0101"'
-n A
इस समय, bashदोनों पोसिक्स और यूनिक्स अनुरूप है। ध्यान दें कि POSIX मोड में, bashअभी भी POSIX अनुरूप नहीं है क्योंकि इसमें आउटपुट नहीं -eहै:
$ env SHELLOPTS=posix bash -c 'echo -e'
$
स्क्रिप्ट के लिए --enable-xpg-echo-defaultऔर --enable-strict-posix-defaultविकल्पों के साथ संकलन समय पर xpg_echo और पॉज़िक्स के लिए डिफ़ॉल्ट मान को परिभाषित किया जा सकता है configure। यह आमतौर पर ओएस / एक्स के हाल के संस्करणों का निर्माण करने के लिए क्या करते हैं /bin/sh। उनके सही दिमाग में कोई यूनिक्स / लिनक्स कार्यान्वयन / वितरण आमतौर पर /bin/bashहालांकि ऐसा नहीं होगा । असल में, यह सच नहीं है, /bin/bashसोलारिस 11 (एक वैकल्पिक पैकेज में) के साथ ओरेकल के जहाजों के साथ बनाया गया लगता है --enable-xpg-echo-default(जो कि सोलारिस 10 में ऐसा नहीं था)।
2. कैसे ksh93के echoव्यवहार बदला जा सकता है।
इसमें ksh93, क्या echoएस्केप अनुक्रम से बाहर निकलता है या नहीं और विकल्पों को पहचानता है $PATHऔर / और $_AST_FEATURESपर्यावरण चर की सामग्री पर निर्भर करता है ।
यदि $PATHकोई घटक शामिल है /5binया उसके /xpgपहले /binया /usr/binघटक है तो यह SysV / UNIX तरीका (दृश्यों का विस्तार करता है, स्वीकार नहीं करता है) का व्यवहार करता है। यदि यह पाया जाता है /ucbया /bsdपहले या यदि $_AST_FEATURES7 में शामिल है UNIVERSE = ucb, तो यह बीएसडी 3 तरह से व्यवहार करता है ( -eविस्तार सक्षम करने, पहचानने के लिए -n)।
डिफ़ॉल्ट सिस्टम निर्भर है, डेबियन पर बीएसडी ( builtin getconf; getconf UNIVERSEksh93 के हाल के संस्करणों में आउटपुट देखें ):
$ ksh93 -c 'echo -n' # default -> BSD (on Debian)
$ PATH=/foo/xpgbar:$PATH ksh93 -c 'echo -n' # /xpg before /bin or /usr/bin -> XPG
-n
$ PATH=/5binary:$PATH ksh93 -c 'echo -n' # /5bin before /bin or /usr/bin -> XPG
-n
$ PATH=/5binary:$PATH _AST_FEATURES='UNIVERSE = ucb' ksh93 -c 'echo -n' # -> BSD
$ PATH=/ucb:/foo/xpgbar:$PATH ksh93 -c 'echo -n' # /ucb first -> BSD
$ PATH=/bin:/foo/xpgbar:$PATH ksh93 -c 'echo -n' # /bin before /xpg -> default -> BSD
3. गूंज के लिए बीएसडी -ई?
-eविकल्प से निपटने के लिए बीएसडी का संदर्भ यहां थोड़ा भ्रामक है। उन विभिन्न और असंगत echoव्यवहारों में से अधिकांश एटी एंड टी में पेश किए गए थे:
\n, \0ooo, \cप्रोग्रामर काम बेंच यूनिक्स (यूनिक्स वी 6 के आधार पर) और शेष ऊर्जा (में \b, \r...) यूनिक्स प्रणाली III में रेफरी ।
-nयूनिक्स V7 में (डेनिस रिची रेफ द्वारा )
-eयूनिक्स V8 में (डेनिस रिची रेफ द्वारा )
-Eसंभवतः संभवतः शुरू में bash(CWRU / CWRU.chlog से संस्करण 1.13.5 में ब्रायन फॉक्स ने इसे 1992-10-18 में जोड़ा था, GNU ने echoइसे कुछ ही समय बाद कॉपी कर दिया था।
जबकि echoकी अंतर्निहित shया BSDs का समर्थन किया है -eदिन वे जल्दी 90 के दशक में इसके लिए Almquist खोल का उपयोग शुरू के बाद से, स्टैंडअलोन echoइस दिन के लिए उपयोगिता यह वहाँ का समर्थन नहीं करता ( FreeBSDecho अभी भी समर्थन नहीं करता है -e, हालांकि यह समर्थन करता है -nकी तरह यूनिक्स V7 (और यह भी \cलेकिन केवल अंतिम तर्क के अंत में))।
की हैंडलिंग -eके लिए जोड़ा गया ksh93है echoबीएसडी में जब ब्रह्मांड 2006 में जारी किया और ksh93r संस्करण में संकलन समय अक्षम किया जा सकता है।
4. 8.31 में जीएनयू इको व्यवहार में बदलाव
Coreutils 8.31 (और के बाद से यह वादा ), जीएनयू echoअब डिफ़ॉल्ट रूप से दृश्यों से बचने जब POSIXLY_CORRECT वातावरण में है, के व्यवहार से मेल करने फैलता bash -o posix -O xpg_echoहै echobuiltin (देखें बग रिपोर्ट )।
5. macOS echo
मैकगो के अधिकांश संस्करणों को ओपनग्रुप से यूनिक्स प्रमाणीकरण प्राप्त हुआ है ।
इनका बिल्ट shकंप्लेंट echoहै क्योंकि यह डिफ़ॉल्ट रूप से सक्षम होने के bashसाथ बनाया गया (बहुत पुराना संस्करण) है xpg_echo, लेकिन उनकी स्टैंड-अलोन echoउपयोगिता नहीं है। env echo -nआउटपुट के बजाय कुछ नहीं -n<newline>, env echo '\n'आउटपुट के \n<newline>बजाय आउटपुट <newline><newline>।
यह /bin/echoFreeBSD में से एक है जो अगर नई दलील को दबाता है यदि पहला तर्क है -n(या 1995 के बाद से) यदि अंतिम तर्क में समाप्त होता है \c, लेकिन UNIX द्वारा आवश्यक किसी भी अन्य बैकस्लैश अनुक्रम का समर्थन नहीं करता है, तो भी नहीं \\।
6. echoकार्यान्वयन जो मनमाने ढंग से डेटा वर्बटिम का उत्पादन कर सकते हैं
सच पूछिये तो, आप भी गिनती कर सकता है कि FreeBSD / MacOS /bin/echoऊपर (न कि उसका खोल के echobuiltin) जहां zshकी echo -E - "$var"या yashकी ECHO_STYLE=raw echo "$var"( printf '%s\n' "$var") लिखा जा सकता है:
/bin/echo "$var
\c"
लागू करने वाले समर्थन -Eऔर -n(या कॉन्फ़िगर किया जा सकता है) भी कर सकते हैं:
echo -nE "$var
"
और zshके echo -nE - "$var"( printf %s "$var") लिखा जा सकता है
/bin/echo "$var\c"
7. _AST_FEATURESऔर एएसटीUNIVERSE
इसका _AST_FEATURESमतलब सीधे तौर पर छेड़छाड़ करना नहीं है, इसका इस्तेमाल कमांड निष्पादन के दौरान एएसटी कॉन्फ़िगरेशन सेटिंग्स को प्रचारित करने के लिए किया जाता है। कॉन्फ़िगरेशन का अर्थ है (undocumented) astgetconf()API के माध्यम से किया जाता है। अंदर ksh93, getconfअंतर्निहित (के साथ builtin getconfया द्वारा सक्षम command /opt/ast/bin/getconf) इंटरफ़ेस करने के लिए हैastgetconf()
उदाहरण के लिए, आप सेटिंग को ( अन्य चीजों के बीच SysV तरीके का व्यवहार करने के builtin getconf; getconf UNIVERSE = attलिए) बदलने के UNIVERSEलिए करेंगे । ऐसा करने के बाद, आप पर्यावरण के चर को देखेंगे ।attecho$_AST_FEATURESUNIVERSE = att
echo -eक्या?