असल में, यह एक पोर्टेबिलिटी (और विश्वसनीयता) मुद्दा है।
प्रारंभ में, 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_CORRECT
posix
अधिकांश प्रणालियों पर डिफ़ॉल्ट व्यवहार:
$ 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_FEATURES
7 में शामिल है UNIVERSE = ucb
, तो यह बीएसडी 3 तरह से व्यवहार करता है ( -e
विस्तार सक्षम करने, पहचानने के लिए -n
)।
डिफ़ॉल्ट सिस्टम निर्भर है, डेबियन पर बीएसडी ( builtin getconf; getconf UNIVERSE
ksh93 के हाल के संस्करणों में आउटपुट देखें ):
$ 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
है echo
builtin (देखें बग रिपोर्ट )।
5. macOS echo
मैकगो के अधिकांश संस्करणों को ओपनग्रुप से यूनिक्स प्रमाणीकरण प्राप्त हुआ है ।
इनका बिल्ट sh
कंप्लेंट echo
है क्योंकि यह डिफ़ॉल्ट रूप से सक्षम होने के bash
साथ बनाया गया (बहुत पुराना संस्करण) है xpg_echo
, लेकिन उनकी स्टैंड-अलोन echo
उपयोगिता नहीं है। env echo -n
आउटपुट के बजाय कुछ नहीं -n<newline>
, env echo '\n'
आउटपुट के \n<newline>
बजाय आउटपुट <newline><newline>
।
यह /bin/echo
FreeBSD में से एक है जो अगर नई दलील को दबाता है यदि पहला तर्क है -n
(या 1995 के बाद से) यदि अंतिम तर्क में समाप्त होता है \c
, लेकिन UNIX द्वारा आवश्यक किसी भी अन्य बैकस्लैश अनुक्रम का समर्थन नहीं करता है, तो भी नहीं \\
।
6. echo
कार्यान्वयन जो मनमाने ढंग से डेटा वर्बटिम का उत्पादन कर सकते हैं
सच पूछिये तो, आप भी गिनती कर सकता है कि FreeBSD / MacOS /bin/echo
ऊपर (न कि उसका खोल के echo
builtin) जहां 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
लिए करेंगे । ऐसा करने के बाद, आप पर्यावरण के चर को देखेंगे ।att
echo
$_AST_FEATURES
UNIVERSE = att
echo -e
क्या?