उद्धरण चिह्नों के साथ "$" ()


12

मैंने यह स्क्रिप्ट लिखी है:

#!/bin/bash
while [ true ] 
do
    currentoutput="$(lsusb)"
    if [ "$currentoutput" != "$lastoutput" ]
    then
        echo "" date and Time >> test.log
        date +%x_r >> test.log
        lastoutput="$(lsusb)"
        lsusb >> test.log
    fi
    sleep 5
done

मैं एक नौसिखिया हूं जो तेजी से सीखने की कोशिश कर रहा है और मुझे चर के उद्धरण चिह्नों के बारे में एक सवाल मिला है ।

$ () के बीच एक वैरिएबल डालें, मैं इसे प्राप्त करता हूं, लेकिन कथन में भी उद्धरण चिह्नों की आवश्यकता क्यों है if? क्या यह नेस्टेड कमांड बनाने के लिए है?


5
ध्यान दें कि while [ true ]एक अनंत लूप का उत्पादन होता है, लेकिन शायद उस कारण के लिए नहीं जिसे आप सोचते हैं कि यह करता है; एक अनंत लूप while [ false ] भी पैदा करता है, क्योंकि एकल तर्क के साथ, [ ... ]यदि यह तर्क गैर-रिक्त स्ट्रिंग है तो सफल होता है। while trueवास्तव में एक कमांड चलाएगा जिसका नाम है true(जो हमेशा सफल होता है)।
चेपनर

4
आप एक चर अंदर नहीं डालते $()। आपने अंदर आज्ञा दी$()
वाइल्डकार्ड

जवाबों:


23

उद्धरण चिह्न "शब्द विभाजन" को रोकते हैं। वह यह है: व्हॉट्सएप वर्णों में कई मदों में चर को तोड़ना (या रिक्त स्थान, टैब पर और अधिक सटीक होना, डिफ़ॉल्ट $IFSशेल चर के मूल्य में परिभाषित के रूप में नया अंक )।

उदाहरण के लिए,

$ var="one two"
$ howmany(){ echo $#;  }
$ howmany $var
2
$ howmany "$var"
1

यहां हम howmanyफ़ंक्शन को परिभाषित करते हैं जो हमें केवल यह बताता है कि कितने स्थितिगत पैरामीटर दिए गए हैं। जैसा कि आप देख सकते हैं, चर के लिए दो आइटम पारित किए जा रहे हैं, और उद्धरण के साथ चर में पाठ को एक इकाई माना जाता है।

यह सही जानकारी के पारित होने के लिए महत्वपूर्ण है। उदाहरण के लिए, यदि चर में फ़ाइल करने के लिए पथ है, और फ़ाइल नाम में पथ कहीं भी है, तो आप जिस कमांड को चलाने का प्रयास कर रहे हैं वह विफल हो सकता है या गलत परिणाम दे सकता है। यदि हम $varचर के साथ एक फ़ाइल बनाने की कोशिश कर रहे थे , touch $varतो दो फाइलें बनाएंगे, लेकिन touch "$var"सिर्फ एक।

वही आपके [ "$currentoutput" != "$lastoutput" ]हिस्से के लिए जाता है । यह विशेष परीक्षण दो तारों पर एक तुलना करता है। जब परीक्षण चलता है, तो [कमांड को 3 तर्क देखने होंगे - एक टेक्स्ट स्ट्रिंग, !=ऑपरेटर और दूसरा टेक्स्ट स्ट्रिंग। दोहरा उद्धरण रखने से शब्द विभाजन से बचा जाता है, और [कमांड वास्तव में उन 3 तर्कों को देखता है। अब यदि चर अयोग्य हैं तो क्या होगा?

$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$ 

यहाँ, शब्द बंटवारा होता है, और इसके बजाय [दो तार helloऔर worldउसके !=बाद दो और तार दिखाई देते हैं hi world। मुख्य बिंदु यह है कि दोहरे उद्धरण चिह्नों के बिना, चर की सामग्री को एक पूरे आइटम के बजाय अलग-अलग इकाइयों के रूप में समझा जाता है।

आदेश प्रतिस्थापन के रूप में दोहरे उद्धरण चिह्नों की आवश्यकता नहीं है

var=$( df )

जहां आपके पास dfकमांड का आउटपुट सेव है var। हालांकि, यह हमेशा एक अच्छी आदत है $(...)कि जब तक आप वास्तव में आउटपुट को अलग-अलग वस्तुओं के रूप में व्यवहार नहीं करना चाहते हैं, तब तक डबल चर और कमांड प्रतिस्थापन को दोहराएं।


एक साइड नोट पर,

while [ true ]

हिस्सा हो सकता है

while true

[एक ऐसा कमांड है जो इसके तर्कों का मूल्यांकन करता है, और [ whatever ]जो भी अंदर है , उसकी परवाह किए बिना हमेशा सच होता है। इसके विपरीत, while trueकमांड का उपयोग करता है trueजो हमेशा सफलता से बाहर निकलने की स्थिति में लौटता है (और ठीक यही whileलूप की जरूरत है)। अंतर थोड़ा अधिक स्पष्टता और कम परीक्षण का है। वैकल्पिक रूप से, आप के :बजाय भी उपयोग कर सकते हैंtrue

echo "" date and Timeभाग में दोहरे उद्धरण चिह्नों को शायद हटाया जा सकता है। वे केवल एक खाली स्ट्रिंग सम्मिलित करते हैं और आउटपुट में अतिरिक्त स्थान जोड़ते हैं। यदि वह वांछित है, तो उन्हें वहां रखने के लिए स्वतंत्र महसूस करें, लेकिन इस मामले में कोई विशेष कार्यात्मक मूल्य नहीं है।

lsusb >> test.log

इस हिस्से को शायद बदला जा सकता है echo "$currentoutput" >> test.log। इसमें lsusbपहले से चलाए जाने के बाद दोबारा चलने का कोई कारण नहीं है currentoutput=$(lsusb)। ऐसे मामलों में जहां अनुरेखण में नई सुर्खियों को संरक्षित करना पड़ता है - एक कमांड को कई बार चलाने में मूल्य को देख सकते हैं, लेकिन lsusbइसके लिए कोई आवश्यकता नहीं है। कम बाहरी कमांड जिसे आप कॉल करते हैं, बेहतर है, क्योंकि प्रत्येक गैर-इन-कमांड कमांड में हर कॉल सीपीयू, मेमोरी उपयोग और निष्पादन समय में खर्च होता है (भले ही कमांड संभवतः मेमोरी से प्री-लोडेड हैं)।


यह सभी देखें:


1
महान जवाब, यदि आप पहले से ही नहीं थे, तो आपको एक किताब लिखनी चाहिए bash। लेकिन पिछले भाग में echo "$currentoutput" >> test.log बेहतर नहीं होना चाहिए printf '%s\n' "$currentoutput" >> test.log?
pLumo

2
@RoVo हाँ, printfपोर्टेबिलिटी के लिए प्राथमिकता दी जानी चाहिए। चूंकि हम यहां बैश-विशिष्ट स्क्रिप्ट का उपयोग कर रहे हैं, इसलिए इसका उपयोग करने के लिए बहाना किया जा सकता है echo। लेकिन आपका अवलोकन बहुत सही है
सर्गी कोलोडियाज़नी

1
@SergiyKolodyazhnyy, ... मुझे यकीन नहीं है कि echoयह पूरी तरह से विश्वसनीय है, भले ही शेल को बैश ( xpg_echoऔर posixझंडे का मूल्य ज्ञात हो); यदि आपका मूल्य हो सकता है -nया -e, यह मुद्रित होने के बजाय गायब हो सकता है।
चार्ल्स डफी

4

में currentoutput="$(lsusb)"lsusb एक चर नहीं है, यह एक आदेश है। यह कथन क्या करता है, यह lsusbकमांड निष्पादित करता है और इसके आउटपुट को currentoutputवेरिएबल में असाइन करता है ।

इसके लिए पुराना सिंटैक्स था

currentoutput=`lsusb`

आप इसे कई उदाहरणों और लिपियों में पा सकते हैं

अपने प्रश्न के दूसरे भाग का उत्तर देने के लिए, if [ ]बस यह है कि कैसे वाक्यविन्यास ifको बाश में परिभाषित किया गया है। Https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html पर और देखें


3
मुझे लगता है कि [ ]वास्तव में यह कहना महत्वपूर्ण है test। आप ifअन्य कमांड के साथ भी स्टेटमेंट का उपयोग कर सकते हैं , क्योंकि यह उनके एक्जिट कोड के 0 या नॉन-जीरो टेस्ट पर निर्भर करता है।
9

... वास्तव में, इसे चलाने की if grep -qe "somestring" fileतुलना में चलाने के लिए बेहतर है grep -qe "somestring" file; if [ $? = 0 ]; then ..., इसलिए यह दावा है कि वाक्यविन्यास if [ ...की परिभाषा का हिस्सा ifकेवल भ्रामक नहीं है, बल्कि बुरी प्रथाओं की ओर जाता है।
चार्ल्स डफी

4

निम्नलिखित बाहरी कमांड चलाता है commandऔर इसका आउटपुट देता है।

"$(command)"

कोष्ठक / कोष्ठक के बिना, यह कमांड चलाने के बजाय एक चर की तलाश करेगा:

"$variable"

के बीच अंतर के रूप में $variableऔर "$variable", इस प्रासंगिक हो जाता है जब $variableस्पेस हैं। उपयोग करते समय "$variable", संपूर्ण चर सामग्री को एक स्ट्रिंग में डाला जाएगा, भले ही सामग्री रिक्त स्थान शामिल हो। $variableचर की सामग्री का उपयोग करते समय कई तर्कों की एक तर्क सूची में विस्तारित किया जा सकता है।


HI @thomasrutter, मुझे क्षमा करें, मेरा मतलब उद्धरण चिह्न है ... मैं अपनी टिप्पणी अब संपादित करता हूं!
शंकराचार्य

1

विरोधाभासी होने के लिए - बैश आपको सलाह देता है कि आप परीक्षण में वैरिएबल को कोट करने से बचने के [[ ... ]]लिए [ ... ]निर्माण का उपयोग करें और इसलिए शब्द विभाजन की संबंधित समस्याएं जो दूसरों ने इंगित की हैं।

[POSIX संगतता के लिए बैश में प्रदान किया जाता है स्क्रिप्ट के तहत मतलब है #!/bin/shया उन लोगों के लिए चलाया जा रहा है, जो कि अधिक भाग के लिए पोर्ट किए जा रहे हैं - अधिकांश भाग के लिए, आपको इसके पक्ष में बचना चाहिए [[

जैसे

# With [ - quotes are needed

$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments

$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"                                                                                                              
they're equal

# versus [[ - quotes not needed

$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal

bashऐसी कोई सिफारिश नहीं करता है; यह प्रदान करता है [[ ... ]] जो अधिक सुविधाजनक हो सकता है और इसमें कुछ कार्यक्षमता है जो [ ... ]नहीं करता है, लेकिन [ ... ] सही तरीके से उपयोग करने में कोई समस्या नहीं है ।
चेपनर

@chepner - शायद मुझे यहाँ स्पष्ट होना चाहिए। यकीन है कि यह बैश मैनपेज में एक स्पष्ट सिफारिश नहीं है, लेकिन दिया [[सब कुछ [करता है और अभी भी कई बार [लोगों को यात्रा करता है और फिर कोशिश करता है और वापस [[लौटने की सुविधाओं [को विफल करने और केवल बिखरे हुए कीड़ों को छोड़ने के लिए - यह कहना उचित है समुदाय सिफारिश में जहाँ तक सबसे अधिक प्रासंगिक बैश शैली गाइड सलाह देंगे कभी नहीं का उपयोग करें[
श्लोम्ब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.