जब आप एलिगेटर में अपनी गर्दन तक होते हैं, तो यह भूलना आसान है कि लक्ष्य दलदल को खत्म करना था।
- लोकप्रिय कहावत
सवाल के बारे में है echo
, और अभी तक जवाब के बहुमत पर ध्यान केंद्रित करने के लिए कैसे एक set +x
आदेश में चुपके है । वहाँ एक बहुत सरल, अधिक प्रत्यक्ष समाधान है:
{ echo "Message"; } 2> /dev/null
(मैं स्वीकार करता हूं कि { …; } 2> /dev/null
अगर मैंने इसे पहले के उत्तर में नहीं देखा था , तो शायद मैंने सोचा भी नहीं होगा।)
यह कुछ हद तक बोझिल है, लेकिन, अगर आपके पास लगातार echo
कमांड का एक ब्लॉक है, तो आपको इसे हर एक पर व्यक्तिगत रूप से करने की आवश्यकता नहीं है:
{
echo "The quick brown fox"
echo "jumps over the lazy dog."
} 2> /dev/null
ध्यान दें कि जब आपको नई सुर्खियाँ चाहिए तो आपको अर्धविराम की आवश्यकता नहीं है।
आप गैर-मानक फ़ाइल डिस्क्रिप्टर (जैसे, 3) पर स्थायी रूप
से खोलने के kenorb के विचार का उपयोग करके /dev/null
और फिर हर समय के 2>&3
बजाय कहकर टाइपिंग का बोझ कम कर सकते हैं 2> /dev/null
।
इस लेखन के समय में पहले चार जवाब कुछ खास कर की आवश्यकता होती है (और, ज्यादातर मामलों, बोझिल में)
हर बार जब आप एक कर echo
। यदि आप वास्तव में चाहते हैं कि सभी echo
कमांड निष्पादन ट्रेस को दबा दें (और आप ऐसा क्यों नहीं करेंगे?), तो आप बहुत सारे कोड को हटाए बिना, विश्व स्तर पर ऐसा कर सकते हैं। सबसे पहले, मैंने देखा कि उपनामों का पता नहीं लगाया गया है:
$ myfunc()
> {
> date
> }
$ alias myalias="date"
$ set -x
$ date
+ date
Mon, Oct 31, 2016 0:00:00 AM # Happy Halloween!
$ myfunc
+ myfunc # Note that function call is traced.
+ date
Mon, Oct 31, 2016 0:00:01 AM
$ myalias
+ date # Note that it doesn’t say + myalias
Mon, Oct 31, 2016 0:00:02 AM
(ध्यान दें कि निम्न स्क्रिप्ट स्निपेट काम करता है यदि शेबंग है #!/bin/sh
, भले ही /bin/sh
बैश करने के लिए एक लिंक है। लेकिन, यदि शेबंग है #!/bin/bash
, तो आपको shopt -s expand_aliases
स्क्रिप्ट में काम करने के लिए उपनाम प्राप्त करने के लिए एक कमांड जोड़ने की आवश्यकता है ।)
तो, मेरी पहली चाल के लिए:
alias echo='{ set +x; } 2> /dev/null; builtin echo'
अब, जब हम कहते हैं echo "Message"
, हम उपनाम कह रहे हैं, जिसका पता नहीं चलता है। उपनाम ट्रेस विकल्प को बंद कर देता है, जबकि set
कमांड से ट्रेस संदेश को दबा देता है (पहले उपयोगकर्ता 505071535 के उत्तर में तकनीक को प्रस्तुत करता है), और फिर वास्तविक echo
कमांड निष्पादित करता है । इससे हमें प्रत्येक echo
कमांड पर कोड को संपादित करने की आवश्यकता के बिना उपयोगकर्ता के 505071535 के उत्तर के समान प्रभाव मिलता है । हालाँकि, यह ट्रेस ट्रेस मोड बंद हो गया। हम set -x
उपनाम (या कम से कम आसानी से नहीं) में नहीं डाल सकते क्योंकि एक उपनाम केवल एक स्ट्रिंग को एक शब्द के लिए प्रतिस्थापित करने की अनुमति देता है; अलियास स्ट्रिंग के किसी भी भाग को तर्कों (जैसे, ) के बाद कमांड में इंजेक्ट नहीं किया जा सकता है
"Message"
। इसलिए, उदाहरण के लिए, यदि स्क्रिप्ट में है
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
date
आउटपुट होगा
+ date
Mon, Oct 31, 2016 0:00:03 AM
The quick brown fox
jumps over the lazy dog.
Mon, Oct 31, 2016 0:00:04 AM # Note that it doesn’t say + date
इसलिए आपको संदेश प्रदर्शित करने के बाद भी ट्रेस विकल्प को फिर से चालू करने की आवश्यकता है - लेकिन लगातार कमांड के प्रत्येक ब्लॉक के बाद केवल एक बार echo
:
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
set -x
date
यह अच्छा होगा यदि हम set -x
एक के बाद स्वचालित बना सकते हैं echo
- और हम थोड़ा अधिक प्रवंचना के साथ कर सकते हैं। लेकिन इससे पहले कि मैं इसे प्रस्तुत करूं, इस पर विचार करें। ओपी उन स्क्रिप्ट्स से शुरू कर रहा है जो एक #!/bin/sh -ex
शेबंग का उपयोग करती हैं । स्पष्ट रूप से उपयोगकर्ता x
शेलबैंग से निकाल सकता है और एक स्क्रिप्ट है जो सामान्य रूप से काम करता है, निष्पादन अनुरेखण के बिना। यह अच्छा होगा यदि हम एक समाधान विकसित कर सकें जो उस संपत्ति को बरकरार रखे। यहां पहले कुछ उत्तर उस संपत्ति को विफल कर देते हैं क्योंकि वे echo
बयानों के बाद "पीछे" ट्रेसिंग करते हैं, बिना शर्त, बिना इस बात के कि क्या यह पहले से ही था।
यह उत्तर स्पष्ट रूप से उस मुद्दे को पहचानने में विफल रहता है, क्योंकि यह प्रतिस्थापित करता है echo
ट्रेस आउटपुट के साथ आउटपुट; इसलिए, यदि ट्रेसिंग बंद हो जाती है तो सभी संदेश गायब हो जाते हैं। मैं अब एक समाधान पेश करूंगा जो एक echo
बयान के बाद सशर्त रूप से पीछे मुड़ जाता है - केवल अगर यह पहले से ही था। इसे ऐसे समाधान में अपग्रेड करना जो बिना शर्त के "बैक" को ट्रेस करता है, तुच्छ है और इसे अभ्यास के रूप में छोड़ दिया जाता है।
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
echo_and_restore() {
builtin echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
$-
विकल्प सूची है; सेट किए गए सभी विकल्पों के अनुरूप अक्षरों का एक संयोजन। उदाहरण के लिए, यदि विकल्प e
और x
विकल्प निर्धारित किए जाते हैं, तो $-
उन अक्षरों का एक जोड़ होगा जो शामिल हैं e
और x
। मेरा नया उपनाम (ऊपर) $-
ट्रेसिंग बंद करने से पहले का मूल्य बचाता है। फिर, ट्रेसिंग बंद होने के साथ, यह एक शेल फ़ंक्शन में नियंत्रण को फेंकता है। यह फ़ंक्शन वास्तविक करता है echo
और फिर यह देखने के लिए जांचता है कि क्या x
विकल्प चालू किया गया था जब उपनाम उतारा गया था। यदि विकल्प चालू था, तो फ़ंक्शन इसे वापस चालू करता है; यदि यह बंद था, तो फ़ंक्शन इसे बंद कर देता है।
आप shopt
स्क्रिप्ट की शुरुआत में उपरोक्त सात लाइनें (आठ, यदि आप शामिल हैं ) सम्मिलित कर सकते हैं और बाकी को अकेले छोड़ सकते हैं।
यह आपको अनुमति देगा
- निम्नलिखित शेबंग लाइनों में से किसी का उपयोग करने के लिए:
#! / बिन / श-ष
#! / बिन / श-ई
#! / बिन / श- x
या सिर्फ सादा#! / Bin / श
और यह उम्मीद के मुताबिक काम करना चाहिए।
- कोड की तरह है
(shebang)
कमांड 1
कमांड 2
कमांड 3
सेट -x
कमांड 4
कमांड 5
कमांड 6
सेट + एक्स
कमांड 7
कमांड 8
कमांड 9
तथा
- कमांड 4, 5, और 6 का पता लगाया जाएगा - जब तक कि उनमें से कोई एक नहीं है
echo
, जिस स्थिति में इसे निष्पादित किया जाएगा, लेकिन पता नहीं लगाया जाएगा। (लेकिन भले ही कमांड 5 एक है echo
, कमांड 6 अभी भी पता लगाया जाएगा।)
- 7, 8, और 9 कमांड का पता नहीं लगाया जाएगा। भले ही कमांड 8 एक है
echo
, कमांड 9 अभी भी पता नहीं लगाया जाएगा।
- कमांड 1, 2, और 3 का पता लगाया जाएगा (जैसे 4, 5 और 6) या नहीं (जैसे 7, 8, और 9) इस बात पर निर्भर करता है कि शेबंग शामिल है या नहीं
x
।
PS मुझे पता चला है कि, मेरे सिस्टम पर, मैं builtin
अपने मध्य उत्तर में कीवर्ड को छोड़ सकता हूं (वह जो केवल एक उपनाम है echo
)। यह आश्चर्य की बात नहीं है; बाश (1) कहता है कि, उर्फ विस्तार के दौरान,…
... एक शब्द जो उपनाम के समान है, दूसरी बार विस्तारित नहीं किया जाता है। इसका मतलब यह है कि उदाहरण के ls
लिए ls -F
, अन्य व्यक्ति उर्फ हो सकता है , और बैश रिप्लेसमेंट टेक्स्ट को पुनरावृत्ति करने की कोशिश नहीं करता है।
बहुत आश्चर्य की बात नहीं, अंतिम उत्तर (जिसके साथ echo_and_restore
) विफल रहता है यदि builtin
कीवर्ड 1 छोड़ दिया गया है । लेकिन, अगर मैं हटाता हूं builtin
और ऑर्डर को स्विच करता हूं तो यह अजीब तरह से काम करता है :
echo_and_restore() {
echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
__________
1 यह अपरिभाषित व्यवहार को जन्म देता है। मैंने देखा है
- एक अनन्त लूप (शायद अनबिके पुनरावृत्ति के कारण),
- एक
/dev/null: Bad address
त्रुटि संदेश, और
- एक कोर डंप।
echo +x; echo "$*"; echo -x
अन्य के बराबर करने का तरीका पेश कर सकता है , तो मैं इसे देखना चाहूंगा।