क्या बकवास में उपयोग के मामले [:] है?


124

मैंने bash (:) में noop खोजा, लेकिन कोई अच्छी जानकारी नहीं मिल पाई। इस ऑपरेटर का सटीक उद्देश्य या उपयोग मामला क्या है?

मैंने निम्नलिखित की कोशिश की और यह मेरे लिए इस तरह काम कर रहा है:

[mandy@root]$ a=11
[mandy@root]$ b=20
[mandy@root]$ c=30
[mandy@root]$ echo $a; : echo $b ; echo $c
10
30

कृपया मुझे बताएं, इस ऑपरेटर का कोई भी उपयोग वास्तविक समय में या किसी भी स्थान पर जहां इसका उपयोग करना अनिवार्य है।


करने के लिए एक नज़र stackoverflow.com/questions/7444504/...
स्टीफ़न Rouberol

ध्यान दें कि :निर्मित में बोर्न शेल और क्ष के साथ-साथ बैश में भी मौजूद है।
घटिया

यह भी देखें :में tldp.org/LDP/abs/html/special-chars.html
choroba

6
यह एक वास्तविक प्रश्न कैसे नहीं है? मुझे लगता है कि यह एक बहुत अच्छा सवाल है। मैं भी इसके लिए एक अच्छा उपयोग है, लेकिन मैं एक जवाब पोस्ट नहीं कर सकता।
स्टीवन लू

जवाबों:


176

यह ऐतिहासिक कारणों से अधिक है। बृहदान्त्र निर्मित :बिलकुल बराबर है truetrueवापसी मूल्य महत्वपूर्ण है, उदाहरण के लिए, अनंत लूप में, इसका उपयोग करना पारंपरिक है :

while true; do
  echo 'Going on forever'
done

:जब शेल सिंटैक्स को कमांड की आवश्यकता होती है तो इसका उपयोग करना पारंपरिक होता है लेकिन आपके पास करने के लिए कुछ नहीं होता है।

while keep_waiting; do
  : # busy-wait
done

:Builtin दिनांकों सभी के लिए रास्ता वापस थॉम्पसन खोल , यह था वर्तमान में यूनिक्स v6:थॉम्पसन शेल के gotoबयान के लिए एक लेबल संकेतक था । लेबल कोई भी पाठ हो सकता है, इसलिए :टिप्पणी संकेतक के रूप में दोगुना हो सकता है (यदि कोई नहीं है goto comment, तो : commentप्रभावी रूप से एक टिप्पणी है)। बॉर्न शैल नहीं था gotoलेकिन रखा :

एक आम मुहावरा जो उपयोग करता :है : ${var=VALUE}, वह सेट करता varहै VALUEअगर यह परेशान था और कुछ भी नहीं करता है अगर varपहले से सेट था। यह निर्माण केवल एक चर प्रतिस्थापन के रूप में मौजूद है, और इस चर प्रतिस्थापन को किसी भी तरह एक कमांड का हिस्सा होने की आवश्यकता है: एक नो-ऑप कमांड अच्छी तरह से कार्य करता है।

यह भी देखें कि कोलन बिलियन का क्या उद्देश्य है?


11
अच्छा सारांश। इसके अलावा, मूल बॉर्न शेल ने #टिप्पणियों (या #!/bin/shशेलबैंग) के लिए उपयोग नहीं किया ; :आदेश की शुरुआत की टिप्पणी, और भोली प्रोग्रामर जो अपनी टिप्पणी में सितारों की एक अच्छा बॉक्स बनाया पेश आना शोक: : ****(या बुरा, : * * *)।
जोनाथन लेफ्लर

3
@JonathanLeffler: मेरे लिए शर्म की बात है, लेकिन मुझे यह नहीं मिला। इससे क्या होगा : * * *?
देवसोलर

7
क्योंकि :एक आदेश है, शेल को अभी भी अपने तर्कों को संसाधित करना है इससे पहले कि वह :उन्हें अनदेखा कर सके। अधिकतर, आप *वर्तमान निर्देशिका में फ़ाइलों की सूची का विस्तार करने के लिए शेल को अतिरिक्त कार्य कर रहे हैं ; यह वास्तव में प्रभावित नहीं करेगा कि स्क्रिप्ट कैसे काम करती है।
चेपनर

मुझे लगता है कि यह आपकी स्क्रिप्ट को विफल कर सकता है यदि आप एक निर्देशिका में बहुत सारी फ़ाइलों के साथ चलते हैं, तो ग्लोब विस्तार कमांड की लंबाई सीमा से अधिक हो जाता है? शायद अगर आपके पास है तो ही set -e। वैसे भी, उम्मीद है कि हम सभी का उपयोग करने के लिए सहमत हो सकते हैं #:)
जैक ओ'कॉनर

2
मैं कभी-कभी उपयोग करता while : ; do ... ; doneहूं अगर मुझे एक त्वरित और गंदा अनंत लूप चाहिए। (आमतौर पर sleepलूप में एक है, और मैं इसे मारने के लिए Ctrl-C टाइप करता हूं।)
कीथ थॉम्पसन

21

यदि मैं सभी कोडों पर टिप्पणी करता हूं तो मैं इसका उपयोग करता हूं। उदाहरण के लिए आपके पास एक परीक्षण है:

if [ "$foo" != "1" ]
then
    echo Success
fi

लेकिन आप अस्थायी रूप से भीतर मौजूद हर चीज पर टिप्पणी करना चाहते हैं:

if [ "$foo" != "1" ]
then
    #echo Success
fi

जो एक वाक्यविन्यास त्रुटि देने के लिए बैश का कारण बनता है:

line 4: syntax error near unexpected token `fi'
line 4: `fi'

बैश में खाली ब्लॉक (डब्ल्यूटीएफ) नहीं हो सकते। तो आप एक नो-ऑप जोड़ते हैं:

if [ "$foo" != "1" ]
then
    #echo Success
    :
fi

या आप लाइनों पर टिप्पणी करने के लिए नो-ऑप का उपयोग कर सकते हैं:

if [ "$foo" != "1" ]
then
    : echo Success
fi

12

यदि आप उपयोग करते हैं set- eतो विफलता नहीं होने पर स्क्रिप्ट से बाहर निकलने || :का एक शानदार तरीका है (यह स्पष्ट रूप से इसे पास करता है)।


1
मैंने कुछ शेल-स्क्रिप्ट-कॉलिंग एप्लिकेशन के लिए इसे उपयोगी पाया है। उदाहरण के लिए, मैक पर ऑटोमेकर त्रुटि पर बाहर निकल जाएगा और आपको यह नहीं बताएगा कि क्यों। लेकिन || :फिर बाद में एक त्रुटि के साथ खुद को संभालने का उपयोग करना exit 0आपको डिबगिंग के दौरान ऐप विंडो में सभी स्टडआउट और स्टेडर प्रदर्शित करने देगा। गौर करें { foo ... 2>&1; } || :कि अधिक जटिल जाल और अगर-थेंस स्थापित करने की तुलना में कौन सा सरल है।
बीजोर

7

आप :एक कमांड की आपूर्ति करने के लिए उपयोग करेंगे जो सफल होता है लेकिन कुछ भी नहीं करता है। इस उदाहरण में "वर्बोसिटी" कमांड को डिफ़ॉल्ट रूप से बंद कर दिया जाता है :। 'V' विकल्प इसे चालू करता है।

#!/bin/sh
# example
verbosity=:                         
while getopts v OPT ; do          
   case $OPT in                  
       v)        
           verbosity=/bin/realpath 
       ;;
       *)
           exit "Cancelled"
       ;;             
   esac                          
done                              

# `$verbosity` always succeeds by default, but does nothing.                              
for i in * ; do                   
  echo $i $($verbosity $i)         
done                              

$ example
   file

$ example -v
   file /home/me/file  

सख्ती से बोलना, एक वैरिएबल के लिए एक मान निर्दिष्ट करना "कुछ करना" है, इसलिए यह आपके केस स्टेटमेंट में कोई त्रुटि नहीं डालता है।
कोडीनिजा

@qodeninja: किसी ने दावा नहीं किया कि चर असाइनमेंट "कुछ नहीं किया"; मुद्दा यह है कि $(verbosity $i)बाद में (और सशर्त) कुछ नहीं करता है।
दौड़

6

aliasतर्कों को अनदेखा करें

कुछ समय के लिए आप एक ऐसा उपनाम चाहते हैं जो कोई तर्क न ले। आप इसका उपयोग कर सकते हैं ::

> alias alert_with_args='echo hello there'

> alias alert='echo hello there;:'

> alert_with_args blabla
hello there blabla

> alert blabla
hello there

नहीं downvoter, लेकिन यह जवाब नहीं दिखाता है कि कैसे :काम करता है, दुर्भाग्य से। आपके द्वारा दिया गया उदाहरण बेमानी लगता है।
कोडेनिन्जा

2
सवाल यह नहीं है कि यह कैसे काम करता है, लेकिन उपयोग मामला क्या है । यह सच है मेरा जवाब stackoverflow.com/a/37170755/6320039 के समान है । लेकिन यह वास्तव में समान उपयोग का मामला नहीं है। मुझे अपने उत्तर को सुधारने में खुशी होगी, लेकिन मैं वास्तव में यहाँ कैसे नहीं जानती हूँ ..
बीएन

1
यह थोड़ा सा कायरता है- एक कोने का मामला, अगर आप करेंगे- लेकिन फिर भी काफी दिलचस्प है और किसी की पिछली जेब में रखने के लिए एक चतुर चाल हो सकती है।
माइक एस

2
उसी के साथ प्राप्त किया जा सकता है#
Zoey Hewll

2
@ZoeyHewll, काफी नहीं। जैसा कि उपनामों को किसी भी तरह के निष्पादन से पहले पाठकीय रूप से प्रतिस्थापित किया जाता है , एक उपनाम का उपयोग करके #वह सब कुछ बना देगा जो एक ही पंक्ति के बाद वाक्यगत रूप से आता है। यह वास्तव में अलग है (विचार करें my_alias arg ; other_command, इसके विपरीत, my_alias arg1 {BACKSLASH}{NEWLINE} arg2), और शायद आप जो चाहते हैं वह नहीं है क्योंकि यह वाक्यविन्यास त्रुटियों का कारण हो सकता है (अनुमान करें कि क्या करेगा while my_alias ; do true ; doneया क्या while true ; do my_alias ; doneकरेगा)।
मैलान

4

एक उपयोग बहु-भाषी टिप्पणियों के रूप में है, या अपने कोड के भाग को परीक्षण के प्रयोजनों के लिए एक फाइल के साथ संयोजन के रूप में उपयोग करके टिप्पणी करना है।

: << 'EOF'

This part of the script is a commented out

EOF

आसपास के उद्धरणों का उपयोग करना न भूलें EOFताकि किसी भी कोड का मूल्यांकन न हो, जैसे $(foo)। यह भी तरह एक सहज ज्ञान युक्त टर्मिनेटर नाम का उपयोग कर के लायक हो सकता है NOTES, SCRATCHPADया TODO


शांत चाल! विशेष रूप से खरोंच नोट्स और कोड के लिए दर्जनों की आवश्यकता होती है जब हार्ड-लिपटे होते हैं। एक साइड इफेक्ट यह है कि टिप्पणी लाइनों के विपरीत, कुछ सिंटैक्स हाइलाइटर्स हेरेडोक्स को अनदेखा करेंगे, उन्हें सामान्य कोड (या कम से कम सादे पाठ) की तरह रंग देंगे। जो कमेंट-आउट कोड की जांच करने, या नीयन टिप्पणी रंग में पैराग्राफ से अपनी आंखों को बचाने के लिए महान हो सकता है। केवल चेतावनी यह है कि इस तरह के ब्लॉक को साझा कोड में टिप्पणी के रूप में नोट किया जाना चाहिए, क्योंकि वाक्यविन्यास अद्वितीय है और भ्रम पैदा कर सकता है। फिर, यह वह शेल है जिसके बारे में हम बात कर रहे हैं, जहां भ्रम की संभावना प्रणालीगत है।
बीजर डे

3

दो मेरे।

POD टिप्पणी एम्बेड करें

का एक बहुत ही मजेदार आवेदन बश स्क्रिप्ट में POD टिप्पणियों को एम्बेड करने के: लिए है , ताकि मैन पेज जल्दी से उत्पन्न हो सकें। बेशक, एक अंततः पर्ल ;-) में पूरी स्क्रिप्ट को फिर से लिखेगा

रन-टाइम फंक्शन बाइंडिंग

यह रन-टाइम पर बाइंडिंग फ़ंक्शंस के लिए एक तरह का कोड पैटर्न है। Fi, एक डिबगिंग फ़ंक्शन केवल कुछ करने के लिए है यदि एक निश्चित ध्वज सेट है:

#!/bin/bash
# noop-demo.sh 
shopt -s expand_aliases

dbg=${DBG:-''}

function _log_dbg {
    echo >&2 "[DBG] $@"
}

log_dbg_hook=':'

[ "$dbg" ] && log_dbg_hook='_log_dbg'

alias log_dbg=$log_dbg_hook


echo "Testing noop alias..."
log_dbg 'foo' 'bar'

आपको मिला:

$ ./noop-demo.sh 
Testing noop alias...
$ DBG=1 ./noop-demo.sh 
Testing noop alias...
[DBG] foo bar

2

कभी-कभी नो-ऑप क्लॉस आपके कोड को अधिक पठनीय बना सकते हैं।

यह एक राय का विषय हो सकता है, लेकिन यहाँ एक उदाहरण है। मान लीजिए कि आपने एक फ़ंक्शन बनाया है जो दो यूनिक्स पथों को ले कर काम करता है। यह एक पथ से दूसरे पथ पर cd के लिए आवश्यक 'परिवर्तन पथ' की गणना करता है। आप अपने फ़ंक्शन पर प्रतिबंध लगाते हैं कि पथ दोनों को '/' से शुरू होना चाहिए या दोनों को नहीं होना चाहिए।

function chgpath() {
    # toC, fromC are the first characters of the argument paths.
    if [[ "$toC" == / && "$fromC" == / ]] || [[ "$toC" != / && "$fromC" != / ]]
    then
        true      # continue with function
    else
        return 1  # Skip function.
    fi

कुछ डेवलपर्स नो-ऑप को हटाना चाहेंगे लेकिन इसका मतलब सशर्त को नकारना होगा:

function chgpath() {
    # toC, fromC are the first characters of the argument paths.
    if [[ "$toC" != / || "$fromC" == / ]] && [[ "$toC" == / || "$fromC" != / ]]
    then
        return 1  # Skip function.
    fi

अब-मेरी राय में-अगर-क्लॉज की शर्तों से ऐसा स्पष्ट नहीं है, जिसमें आप कार्य करना छोड़ना चाहते हैं। नो-ऑप को खत्म करने के लिए और इसे स्पष्ट रूप से करने के लिए, आप फ़ंक्शन से बाहर आई-क्लॉज को स्थानांतरित करना चाहेंगे:

    if [[ "$toC" == / && "$fromC" == / ]] || [[ "$toC" != / && "$fromC" != / ]]
    then
        cdPath=$(chgPath pathA pathB)   # (we moved the conditional outside)

यह बेहतर लग रहा है, लेकिन कई बार हम ऐसा नहीं कर सकते हैं; हम चाहते हैं कि चेक फंक्शन के अंदर किया जाए।

तो ऐसा कितनी बार होता है? अक्सर नहीं। शायद साल में एक या दो बार। यह अक्सर पर्याप्त होता है, कि आपको इसके बारे में पता होना चाहिए। जब मुझे लगता है कि यह मेरे कोड की पठनीयता (भाषा की परवाह किए बिना) को सुधारता है तो मैं इसका इस्तेमाल करने से नहीं कतराता।


3
यदि आप के उद्देश्य के बारे में एक प्रश्न का उत्तर दे रहे हैं :, तो आपको उत्तर में उपयोग करना चाहिए :, न trueकि। जैसा कि कहा गया है, यहाँ सशर्त नकारना लिए सबसे आसान तरीका एक का उपयोग करने के लिए है [[ ... ]]आदेश और अवश्य लगा दें !: if ! [[ ( ... && ... ) || ( ... && ... ) ]]; then
chepner

1
आह, बहुत अच्छा, और मुझे अपना जवाब देना चाहिए। हम्मम .... मैं अभी भी उन उदाहरणों के बारे में सोच रहा हूं, जहां मुझे नो-ऑप क्लॉज का इस्तेमाल करना था। यह मेरे साथ आया सबसे अच्छा है।
बिटियाडॉट

यह वास्तव में सिर्फ पश्चगामी संगतता के लिए बरकरार रखा गया है, हालांकि : ${...=...}यकीनन इससे कम अजीब है true ${...=...}। कुछ के रूप में अच्छी तरह से मरोड़ के लिए पसंद while :; doकर सकते हैं while true; do
शेपनर

2

इस उत्तर से कुछ हद तक संबंधित है , मुझे पॉलीग्लॉट स्क्रिप्ट को हैक करने के लिए यह सुविधाजनक नहीं है । उदाहरण के लिए, यहां बैश और वैंपस्क्रिप्ट के लिए एक मान्य टिप्पणी है:

":" #    this is a comment
":" #    in bash, ‘:’ is a no-op and ‘#’ starts a comment line
":" #    in vimscript, ‘"’ starts a comment line

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


जैसे कि कोई व्यक्ति पॉलीग्लॉट लिपि (इसके अलावा शांत होने) के रूप में इस तरह की मुश्किल काम क्यों करेगा: यह उन स्थितियों में मददगार साबित होता है, जहां हम आम तौर पर कई अलग-अलग भाषाओं में कई स्क्रिप्ट फ़ाइलों को लिखने के Xलिए फाइल का हवाला देते हुए लिखते हैं Y

ऐसी स्थिति में, दोनों लिपियों को एक एकल, पॉलीग्लॉट फ़ाइल में मिलाकर किसी भी कार्य को Xकरने के लिए पथ का निर्धारण करने से बचा जाता है Y(यह बस है "$0")। इससे भी महत्वपूर्ण बात, यह कार्यक्रम को स्थानांतरित करने या वितरित करने के लिए अधिक सुविधाजनक बनाता है।

  • एक सामान्य उदाहरण। शेबंग के साथ एक प्रसिद्ध, लंबे समय से स्थायी मुद्दा है: अधिकांश सिस्टम (लिनक्स और साइगविन सहित) केवल एक तर्क को दुभाषिया को पारित करने की अनुमति देते हैं । निम्नलिखित शेबंग:

    #!/usr/bin/env interpreter --load-libA --load-libB

    निम्नलिखित कमांड को आग देगा:

    /usr/bin/env "interpreter --load-libA --load-libB" "/path/to/script"

    और इरादा नहीं:

    /usr/bin/env interpreter --load-libA --load-libB "/path/to/script"

    इस प्रकार, आप एक आवरण स्क्रिप्ट लिखना समाप्त करेंगे, जैसे:

    #!/usr/bin/env sh
    /usr/bin/env interpreter --load-libA --load-libB "/path/to/script"

    यह वह जगह है जहां पॉलीग्लोसिया चरण में प्रवेश करती है।

  • एक अधिक विशिष्ट उदाहरण। मैंने एक बार एक बैश स्क्रिप्ट लिखी थी, जिसने अन्य चीजों के अलावा, विम का आह्वान किया था। मुझे विम को अतिरिक्त सेटअप देने की आवश्यकता थी, जिसे विकल्प के साथ किया जा सकता था --cmd "arbitrary vimscript command here"। हालाँकि, यह सेटअप पर्याप्त था, ताकि इसे स्ट्रिंग में इनलाइन करना भयानक (यदि संभव हो तो) भयानक होता। इसलिए, एक बेहतर समाधान यह था कि इसे कुछ कॉन्फ़िगरेशन फ़ाइल में एक्स्टेंसो में लिखा जाए , फिर विम को उस फ़ाइल के साथ पढ़ा जाए -S "/path/to/file"। इसलिए मैंने एक पॉलीग्लॉट बैश / विम्सस्क्रिप्ट फ़ाइल के साथ समाप्त किया।


1

मैंने डिफ़ॉल्ट स्क्रिप्ट को परिभाषित करने के लिए इसका उपयोग स्क्रिप्ट में भी किया है।


: ${VARIABLE1:=my_default_value}
: ${VARIABLE2:=other_default_value}
call-my-script ${VARIABLE1} ${VARIABLE2}

0

मान लें कि आपके पास एक ऐसी कमांड है जिसे आप दूसरे की सफलता के लिए श्रृंखला बनाना चाहते हैं:

cmd="some command..."
$cmd
[ $? -eq 0 ] && some-other-command

लेकिन अब आप सशर्त रूप से आदेशों को निष्पादित करना चाहते हैं और आप उन आदेशों को दिखाना चाहते हैं जिन्हें निष्पादित किया जाएगा (शुष्क-रन):

cmd="some command..."
[ ! -z "$DEBUG" ] && echo $cmd
[ -z "$NOEXEC" ] && $cmd
[ $? -eq 0 ] && {
    cmd="some-other-command"
    [ ! -z "$DEBUG" ] && echo $cmd
    [ -z "$NOEXEC" ] && $cmd
}

इसलिए यदि आप DEBUG और NOEXEC सेट करते हैं, तो दूसरी कमांड कभी भी दिखाई नहीं देती है। इसका कारण यह है कि पहला आदेश कभी भी निष्पादित नहीं होता है (क्योंकि NOEXEC खाली नहीं है) लेकिन उस तथ्य का मूल्यांकन आपको 1 की वापसी के साथ छोड़ देता है, जिसका अर्थ है कि अधीनस्थ कमांड कभी भी निष्पादित नहीं करता है (लेकिन आप इसे सूखा रन के लिए चाहते हैं)। इसे ठीक करने के लिए आप स्टॉप पर बचे एक्ज़िट वैल्यू को नॉच के साथ रीसेट कर सकते हैं:

[ -z "$NOEXEC" ] && $cmd || :
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.