बैश [[]] कमांड के अंदर स्वचालित चर विस्तार


13

जब एक चर में dereferencing bash, आपको $साइन का उपयोग करना होगा । फिर भी, ऐसा लगता है कि निम्नलिखित ठीक काम कर रहा है:

x=5
[[ x -gt 2 ]]

क्या कोई इसे समझा सकता है?

संपादित करें: (अधिक जानकारी)

मेरा क्या मतलब है कि कैसे और क्यों [[]] कमांड $ चर के बिना मेरे चर x को dereferencing है। और हां, अगर x = 1, कथन का मूल्यांकन गलत (वापसी स्थिति 1) के लिए किया जाता है


2
"सिर्फ ठीक काम करने" से आपका क्या मतलब है? और अगर आपके x=1द्वारा पीछा किया जाता है तो क्या आपका आकलन बदलता है [[ x -gt 2]]?
nohillside

मेरा मतलब है: कैसे और क्यों [[]] कमांड $ चर के बिना मेरे चर x को डीफ़रेंस कर रहा है। और हाँ, यदि x = 1, कथन गलत है (स्थिति 1 लौटें)
अतिथि 21

जवाबों:


9

कारण यह है कि -eqतर्कों के एक अंकगणितीय मूल्यांकन को बल देता है।

एक अंकगणितीय ऑपरेटर: -eq, -gt, -lt, -ge, -leऔर -neएक के अंदर [[ ]](ksh में, zsh और बैश) स्वचालित रूप से सी भाषा के रूप में चर नाम का विस्तार करने का मतलब है, एक अग्रणी के लिए की जरूरत नहीं $

  • पुष्टि के लिए हमें bash स्रोत कोड देखना होगा। मैनुअल कोई प्रत्यक्ष पुष्टि प्रदान नहीं करता है ।

    test.cअंकगणित ऑपरेटरों के प्रसंस्करण के अंदर इस समारोह में आते हैं:

    arithcomp (s, t, op, flags)

    कहां sऔर tदोनों ऑपरेंड हैं। ऑपरेशंस को इस फ़ंक्शन को सौंप दिया गया है:

    l = evalexp (s, &expok);
    r = evalexp (t, &expok);

    फ़ंक्शन evalexpको अंदर परिभाषित किया गया है expr.c, जिसमें यह हेडर है:

    /* expr.c -- arithmetic expression evaluation. */

    तो, हाँ, एक अंकगणितीय ऑपरेटर के दोनों पक्ष अंकगणितीय अभिव्यक्ति मूल्यांकन में (सीधे) आते हैं। सीधे तौर पर, नहीं, लेकिन, अगर नहीं।


व्यवहार में, साथ:

 $ x=3

यह दोनों विफल:

 $ [[ x = 4 ]] && echo yes || echo no
 no

 $ [[ x = 3 ]] && echo yes || echo no
 no

जो सही है, xउसका विस्तार नहीं किया जा रहा है और xयह संख्या के बराबर नहीं है।

तथापि:

 $ [[ x -eq 3 ]] && echo yes || echo no
 yes

 $ [[ x -eq 4 ]] && echo yes || echo no
 no

नामांकित चर का xविस्तार होता है ($ के बिना भी)।

यह […]zsh या bash (यह ksh में करता है) के लिए नहीं होता है ।


यह वही है जो अंदर होता है $((…)):

 $ echo $(( x + 7 ))
 10

और, कृपया यह समझ लें कि यह (बहुत) पुनरावर्ती (डैश और यश को छोड़कर) है:

 $ a=b b=c c=d d=e e=f f=3
 $ echo "$(( a + 7 ))" 
 10

A 😮

और काफी जोखिम भरा:

 $ x='a[$(date -u)]'
 $ [[ x -eq 3 ]] && echo yes || echo no
 bash: Tue Dec  3 23:18:19 UTC 2018: syntax error in expression (error token is "Dec  3 23:18:19 UTC 2018")

वाक्य रचना त्रुटि को आसानी से टाला जा सकता है:

 $ a=3; x='a[$(date -u >/dev/tty; echo 0)]'

 $ [[ x -eq 3 ]] && echo yes || echo no
 Tue Dec  4 09:02:06 UTC 2018
 yes

जैसा कि कहा जाता है: अपने इनपुट को पवित्र करें

 $ [[ ${x//[^0-9]} -eq 3 ]] && echo yes || echo no
 no

😮 का अंत


दोनों (पुराने) बाहरी /usr/bin/test(बिल्टिन नहीं test) और अभी भी पुराने और बाहरी दोनों केवल पूर्णांकों (और जाहिर तौर पर, केवल दशमलव पूर्णांक) की अभिव्यक्ति काexpr विस्तार नहीं करते हैं :

 $ /usr/bin/test "x" -eq 3
 /usr/bin/test: invalid integer x

 $ expr x + 3
 expr: non-integer argument

दिलचस्प। यह बताना मुश्किल नहीं है कि यह कैसे संभव है - [[एक कीवर्ड होने के नाते , ऑपरेटर और ऑपरेंड का पता लगाया जाता है जब कमांड पढ़ा जाता है और विस्तार के बाद नहीं। इस प्रकार [[कह सकते -eqहैं, की तुलना में अधिक स्मार्ट तरीके से इलाज कर सकते हैं [। लेकिन मुझे आश्चर्य है कि: हम यौगिक आदेशों की व्याख्या करने के लिए तर्क की मार के उपयोग के बारे में दस्तावेज कहां से पा सकते हैं? यह मेरे लिए काफी स्पष्ट नहीं लगती है और मैं जाहिरा तौर पर में संतोषजनक स्पष्टीकरण प्राप्त करने में असमर्थ हूँ manया info bash
fra- सान

बैश यह दस्तावेज नहीं है कहीं भी मुझे मिल सकता है। आदमी ksh93 में एक प्रकार का वर्णन है : निम्नलिखित अप्रचलित अंकगणितीय तुलनाओं की भी अनुमति है: exp1 -eq exp2मैन zshbuiltins अंकगणितीय संचालकों के अनुभाग में यह पाठ है जो अंकगणितीय अभिव्यक्तियों के बजाय पूर्णांक तर्कों की अपेक्षा करता है । जो इस बात की पुष्टि करता है कि इस तर्क में निर्दिष्ट शर्तों के तहत परीक्षण निर्मित बिलिन द्वारा कुछ तर्कों को अंकगणितीय अभिव्यक्तियों के रूप में माना जाता है । मैं स्रोत कोड के साथ पुष्टि करूँगा ... ....test
NotAnUnixNazi

7

संख्यात्मक तुलना की ऑपरेंड -eq, -gt, -lt, -ge, -leऔर -neअंकगणित अभिव्यक्ति के रूप में लिया जाता है। कुछ सीमा के साथ, उन्हें अभी भी एकल शेल शब्द होने की आवश्यकता है।

अंकगणितीय अभिव्यक्ति में चर नामों का व्यवहार शैल अंकगणित में वर्णित है :

शेल चर को ऑपरेंड के रूप में अनुमति दी जाती है; अभिव्यक्ति के मूल्यांकन से पहले पैरामीटर विस्तार किया जाता है। एक अभिव्यक्ति के भीतर, शेल चर भी पैरामीटर विस्तार वाक्यविन्यास का उपयोग किए बिना नाम से संदर्भित किया जा सकता है। एक शेल वैरिएबल जो अशक्त या अशांत है 0 का मूल्यांकन करता है जब पैरामीटर विस्तार वाक्यविन्यास का उपयोग किए बिना नाम से संदर्भित होता है।

और भी:

एक चर के मूल्य का मूल्यांकन एक अंकगणितीय अभिव्यक्ति के रूप में किया जाता है जब इसे संदर्भित किया जाता है

लेकिन मैं वास्तव में प्रलेखन का हिस्सा नहीं ढूँढ सकता, जहां यह कहा गया है कि संख्यात्मक तुलना अंकगणितीय अभिव्यक्ति लेती है। इसके तहत सशर्त कंस्ट्रक्शंस में वर्णित नहीं है [[, और न ही बैश कंडिशनल एक्सप्रेशंस में इसका वर्णन किया गया है ।

लेकिन, प्रयोग से, जैसा कि ऊपर कहा गया है, यह काम करता है।

तो, इस तरह से काम करता है:

a=6
[[ a -eq 6 ]] && echo y 
[[ 1+2+3 -eq 6 ]] && echo y
[[ "1 + 2 + 3" -eq 6 ]] && echo y

यह भी (चर के मूल्य का मूल्यांकन किया जाता है):

b='1 + 2 + 3'
[[ b -eq 6 ]] && echo y

लेकिन यह नहीं है; जब [[ .. ]]पार्स किया जाता है तो यह एक भी शेल शब्द नहीं होता है, इसलिए सशर्त में एक सिंटैक्स त्रुटि होती है:

[[ 1 + 2 + 3 -eq 6 ]] && echo y

अन्य अंकगणितीय संदर्भों में, व्हाट्सएप के बिना अभिव्यक्ति की कोई आवश्यकता नहीं है। यह प्रिंट 999, चूंकि कोष्ठक स्पष्ट रूप से सूचकांक में अंकगणितीय अभिव्यक्ति का परिसीमन करता है:

a[6]=999; echo ${a[1 + 2 + 3]}

दूसरी ओर, =तुलना एक पैटर्न मैच है , और इसमें अंकगणित शामिल नहीं है, और न ही एक अंकगणितीय संदर्भ (सशर्त निर्माण) में किया गया स्वचालित चर विस्तार:

जब ऑपरेटरों ==और !=ऑपरेटरों का उपयोग किया जाता है, तो ऑपरेटर के दाईं ओर के स्ट्रिंग को एक पैटर्न माना जाता है और पैटर्न मिलान में नीचे वर्णित नियमों के अनुसार मिलान किया जाता है, जैसे कि एक्सग्लोब शेल विकल्प सक्षम किया गया था। =ऑपरेटर के समान है ==

तो यह गलत है क्योंकि तार स्पष्ट रूप से अलग हैं:

[[ "1 + 2 + 3" = 6 ]] 

जैसा कि यह है, भले ही संख्यात्मक मान समान हों:

[[ 6 = 06 ]] 

और यहाँ भी, तार ( xऔर 6) की तुलना की जाती है, वे अलग हैं:

x=6
[[ x = 6 ]]

यह चर का विस्तार करेगा, हालांकि, यह सच है:

x=6
[[ $x = 6 ]]

वास्तव में प्रलेखन का हिस्सा नहीं मिल सकता है जहां यह कहा गया है कि संख्यात्मक तुलना अंकगणितीय अभिव्यक्तियां लेती है। पुष्टि में है कोड
NotAnUnixNazi

निकटतम बात यह है कि विवरण का arg1 OP arg2कहना है कि आर्ग सकारात्मक या नकारात्मक पूर्णांक हो सकते हैं, जो मुझे लगता है कि इसका अर्थ यह माना जाता है कि उन्हें अंकगणितीय अभिव्यक्तियों के रूप में माना जाता है। भ्रामक रूप से, इसका तात्पर्य यह भी है कि वे शून्य नहीं हो सकते। :)
बरमार

@ बरम, एह, सही। लेकिन यह संख्यात्मक तुलनाओं पर [भी लागू होता है, और वहां वे अंकगणितीय अभिव्यक्तियाँ नहीं हैं। इसके बजाय, बैश गैर-पूर्णांक के बारे में शिकायत करता है।
ilkkachu

@ilkkachu [एक बाहरी कमांड है, इसमें शेल चरों की पहुंच नहीं है। यह अक्सर एक अंतर्निहित कमांड के साथ अनुकूलित होता है, लेकिन यह अभी भी वैसा ही व्यवहार करता है।
बरमार

@ बरमार, मेरा क्या मतलब था कि "Arg1 और arg2 वाक्यांश सकारात्मक या नकारात्मक पूर्णांक हो सकते हैं।" बैश कंडिशनल एक्सप्रेशंस में दिखाई देता है , और यह सूची [बस के साथ ही लागू होती है [[। यहां तक ​​कि [, के लिए -eqऔर दोस्तों के लिए ऑपरेंड / पूर्णांक होना चाहिए, ताकि विवरण भी लागू हो। "मतलब पूर्णांक होना चाहिए" का अर्थ "अंकगणितीय अभिव्यक्तियों के रूप में व्याख्या किया गया है" दोनों मामलों में लागू नहीं होता है। (संभवतः [एक साधारण आदेश की तरह अभिनय करने के कारण कम से कम , जैसा कि आप कहते हैं।)
ilkachachu

1

हां, आपका अवलोकन सही है, चर विस्तार डबल ब्रैकेट के तहत अभिव्यक्तियों पर किया जाता है [[ ]], इसलिए आपको $एक चर नाम के सामने रखने की आवश्यकता नहीं है ।

यह bashमैनुअल में स्पष्ट रूप से कहा गया है :

[[अभिव्यक्ति]]

(...) शब्द विभाजन और पथनाम विस्तार [[और]] के बीच के शब्दों पर नहीं किया जाता है; टिल्ड विस्तार, पैरामीटर और चर विस्तार, अंकगणितीय विस्तार, कमांड प्रतिस्थापन, प्रक्रिया प्रतिस्थापन, और उद्धरण हटाने का प्रदर्शन किया जाता है।

ध्यान दें कि यह एकल-ब्रैकेट संस्करण का मामला नहीं है [ ], जैसा [कि एक शेल कीवर्ड (सिंटैक्स) नहीं है, बल्कि एक कमांड (बैश में यह बिल्ट है, अन्य शेल बाहरी, परीक्षण के लिए उपयोग किया जा सकता है)।


1
जवाब देने के लिए धन्यवाद। ऐसा लगता है कि यह केवल संख्या के लिए काम कर रहा है। x = शहर [[$ x == शहर]] यह $ चिन्ह के बिना काम नहीं करता है।
अतिथि

3
ऐसा लगता है कि यहां अधिक है: (x=1; [[ $x = 1 ]]; echo $?)रिटर्न 0, (x=1; [[ x = 1 ]]; echo $?)रिटर्न 1, अर्थात xजब हम तारों की तुलना करते हैं, तो पैरामीटर विस्तार नहीं किया जाता है। यह व्यवहार अंकगणित मूल्यांकन की तरह दिखता है जो अंकगणित के विस्तार से उत्पन्न होता है, अर्थात इसमें क्या होता है (x=1; echo $((x+1)))। (अंकगणितीय मूल्यांकन के बारे में, man bashकहते हैं कि "एक अभिव्यक्ति के भीतर, शेल चर भी पैरामीटर विस्तार वाक्यविन्यास का उपयोग किए बिना नाम से संदर्भित किया जा सकता है)
fra-san

@ fra-san वास्तव में, क्योंकि -gtऑपरेटर को उम्मीद है कि संख्या पूरी अभिव्यक्ति का पुनर्मूल्यांकन किया जाता है जैसे कि अंदर (()), दूसरी तरफ ==स्ट्रिंग की अपेक्षा है ताकि पैटर्न-मिलान फ़ंक्शन ट्रिगर हो। मैं स्रोत कोड में खुदाई नहीं किया था, लेकिन उचित लगता है।
जिमीज

[एक बैश में निर्मित शेल है।
निजाम मोहम्मद

1
@NizamMohamed यह एक बिलिन है, लेकिन यह अभी भी एक कीवर्ड नहीं है।
Kusalananda
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.