बैश में डबल और सिंगल स्क्वायर ब्रैकेट में क्या अंतर है?


426

मैं बस सोच रहा था कि वास्तव में क्या अंतर है

[[ $STRING != foo ]]

तथा

[ $STRING != foo ]

इसके अलावा, बाद वाला पॉज़िक्स-कम्प्लायंट है, जो श में पाया जाता है और पूर्व एक विस्तार है जो बैश में पाया जाता है।


1
मामले में आप भी एक के संदर्भ में उदाहरण के लिए सभी में कोई कोष्ठक का उपयोग कर, के बारे में सोच रहे थे ifबयान, देख mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D
कीव

इसके अलावा, उबंटू के डॉक्स से: wiki.ubuntu.com/…
रेडिस्टाओ

जवाबों:


309

कई अंतर हैं। मेरी राय में, कुछ सबसे महत्वपूर्ण हैं:

  1. [बैश और कई अन्य आधुनिक गोले में एक बिलिन है। बिलिन एक समापन की अतिरिक्त आवश्यकता के [समान है । बिल्डरों और कार्यक्षमता का अनुकरण और उनकी सीमाओं के साथ ताकि स्क्रिप्ट्स पीछे की ओर संगत हों। मूल निष्पादनयोग्य अभी भी ज्यादातर POSIX अनुपालन और पीछे की संगतता के लिए मौजूद हैं। बाश में कमांड चलाना इंगित करता है कि डिफ़ॉल्ट रूप से एक बिलिन के रूप में व्याख्या की गई है। (नोट: केवल पर निष्पादनयोग्य के लिए लग रहा है पथ और के बराबर है )test][test/bin/[/bin/testtype [[which [type -p [
  2. [[के रूप में संगत नहीं है, यह जरूरी नहीं कि जो कुछ भी /bin/shबिंदुओं के साथ काम करेगा । तो [[अधिक आधुनिक बैश / Zsh / Ksh विकल्प है।
  3. क्योंकि [[शेल में बनाया गया है और विरासत की आवश्यकताएं नहीं हैं, आपको IFS चर पर आधारित शब्द विभाजन के बारे में चिंता करने की आवश्यकता नहीं है, जो रिक्त स्थान के साथ स्ट्रिंग का मूल्यांकन करने वाले चर पर गड़बड़ करने के लिए है। इसलिए, आपको वास्तव में चर को दोहरे उद्धरण चिह्नों में रखने की आवश्यकता नहीं है।

अधिकांश भाग के लिए, बाकी सिर्फ कुछ अच्छे सिंटैक्स हैं। अधिक अंतर देखने के लिए, मैं इस लिंक को अक्सर पूछे जाने वाले प्रश्न का उत्तर देने की सलाह देता हूं: परीक्षण, [और [] के बीच अंतर क्या है? । वास्तव में, यदि आप बैश स्क्रिप्टिंग के बारे में गंभीर हैं, तो मैं FAQ, नुकसान और गाइड सहित संपूर्ण विकि पढ़ने की सलाह देता हूं । गाइड अनुभाग से परीक्षण अनुभाग इन अंतरों को भी बताता है, और क्यों लेखक (लेखक) को लगता है कि एक बेहतर विकल्प है यदि आपको पोर्टेबल होने के बारे में चिंता करने की आवश्यकता नहीं है। मुख्य कारण हैं:[[

  1. आपको परीक्षण के बायीं ओर को उद्धृत करने के बारे में चिंता करने की ज़रूरत नहीं है ताकि यह वास्तव में एक चर के रूप में पढ़ा जा सके।
  2. आपको < >इनपुट पुनर्निर्देशन के रूप में मूल्यांकन न करने के लिए बैकस्लैश की तुलना में कम और अधिक से अधिक भागना नहीं है, जो कि ओवरराइटिंग फ़ाइलों द्वारा कुछ सामान को गड़बड़ कर सकता है। यह फिर से [[एक बेसिन होने के लिए वापस चला जाता है । यदि [(परीक्षण) एक बाहरी कार्यक्रम है, तो शेल को मूल्यांकन करने के तरीके में एक अपवाद बनाना होगा <और >केवल अगर /bin/testइसे बुलाया जा रहा है, जो वास्तव में समझ में नहीं आएगा।

5
धन्यवाद, बैश एफएक्यू का लिंक वह था जिसकी मुझे तलाश थी (उस पेज के बारे में नहीं पता था, धन्यवाद)।
0x89

2
मैंने आपकी पोस्ट को इस जानकारी के साथ संपादित किया है, लेकिन [और परीक्षण को बिलिंस के रूप में निष्पादित किया गया है। बिल्डरों को / बिन / [और / बिन / परीक्षण को बदलने के लिए डिज़ाइन किया गया था लेकिन बायनेरिज़ की सीमाओं को भी पुन: पेश करने की आवश्यकता थी। कमांड 'प्रकार [' सत्यापित करता है कि बिलिन का उपयोग किया गया है। 'जो [' PATH पर केवल निष्पादक की खोज करता है और 'type -P [' के बराबर है
klynch

133

संक्षेप में:

[बैश बिलिन है

[[]] बैश कीवर्ड हैं

कीवर्ड: कीवर्ड बिल्‍ट बिल्‍डिंग की तरह होते हैं, लेकिन मुख्‍य अंतर यह है कि विशेष पार्सिंग नियम उन पर लागू होते हैं। उदाहरण के लिए, [एक बैश बिलियन है, जबकि [[एक बैश कीवर्ड है। वे दोनों सामान के परीक्षण के लिए उपयोग किए जाते हैं, लेकिन चूंकि [[बिलियन के बजाय एक कीवर्ड है, यह कुछ विशेष पार्सिंग नियमों से लाभ देता है जो इसे बहुत आसान बनाते हैं:

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

पहला उदाहरण एक त्रुटि देता है क्योंकि bash फ़ाइल b को कमांड [a] पर पुनर्निर्देशित करने की कोशिश करता है। दूसरा उदाहरण वास्तव में वही करता है जो आप उससे उम्मीद करते हैं। चरित्र <अब फ़ाइल पुनर्निर्देशन ऑपरेटर का अपना विशेष अर्थ नहीं है।

स्रोत: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments


3
[POSIX शेल कमांड है; इसे बनाने की आवश्यकता नहीं है। ]यह केवल एक तर्क है जो कि कमांड के लिए दिखता है, ताकि वाक्यविन्यास संतुलित हो। कमांड एक पर्यायवाची है, testसिवाय इसके कि testकोई समापन नहीं दिखता है ]
कज़


81

व्यवहार में अंतर

बैश 4.3.11 पर कुछ अंतर:

  • POSIX बनाम बैश एक्सटेंशन:

  • मैजिक बनाम रेगुलर कमांड

    • [ एक अजीब नाम के साथ सिर्फ एक नियमित आदेश है।

      ]सिर्फ एक तर्क है [जो आगे के तर्कों का उपयोग करने से रोकता है।

      Ubuntu 16.04 वास्तव में इसके लिए एक निष्पादन योग्य है जो /usr/bin/[कोरुटिल्स द्वारा प्रदान किया गया है, लेकिन बैश बिल्ट-इन संस्करण पूर्वता लेता है।

      बैश कमांड को पार्स करने के तरीके में कोई बदलाव नहीं किया गया है।

      विशेष रूप से, <पुनर्निर्देशन होता है, &&और ||कई आदेशों को समाप्‍त ( )करता है \, जब तक कि बच नहीं जाता , तब तक उप-जनरेट करता है , और शब्‍द विस्‍तार सामान्य रूप से होता है।

    • [[ X ]]एक एकल निर्माण है जिसे Xजादुई रूप से पार्स किया जाता है। <, और &&, विशेष रूप से व्यवहार किया जाता है, और शब्द विभाजन नियम अलग हैं।||()

      आगे =और भी अंतर हैं जैसे और =~

      Bashese में: [एक अंतर्निहित कमांड है, और [[एक कीवर्ड है: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-bword

  • <

  • && तथा ||

    • [[ a = a && b = b ]]: सत्य, तार्किक और
    • [ a = a && b = b ]: सिंटैक्स त्रुटि, &&और कमांड विभाजक के रूप में पार्सcmd1 && cmd2
    • [ a = a -a b = b ]: समकक्ष, लेकिन POSIX, द्वारा पदावनत
    • [ a = a ] && [ b = b ]: POSIX और विश्वसनीय समकक्ष
  • (

    • [[ (a = a || a = b) && a = b ]]: असत्य
    • [ ( a = a ) ]: वाक्यविन्यास त्रुटि, ()एक उपधारा के रूप में व्याख्या की जाती है
    • [ \( a = a -o a = b \) -a a = b ]: समतुल्य, लेकिन ()पोसिक्स द्वारा पदावनत किया जाता है
    • { [ a = a ] || [ a = b ]; } && [ a = b ]POSIX बराबर 5
  • विस्तार और विभाजन (ग्लोब + ग्लोब) पर शब्द विभाजन और फ़ाइल नाम

    • x='a b'; [[ $x = 'a b' ]]: सच है, उद्धरण की जरूरत नहीं है
    • x='a b'; [ $x = 'a b' ]: सिंटैक्स त्रुटि, के लिए फैलता है [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: सिंटैक्स त्रुटि यदि वर्तमान निर्देशिका में एक से अधिक फ़ाइल है।
    • x='a b'; [ "$x" = 'a b' ]: POSIX बराबर
  • =

    • [[ ab = a? ]]: सच है, क्योंकि यह पैटर्न मिलान ( * ? [जादू है) करता है। मौजूदा निर्देशिका में फ़ाइलों के लिए ग्लोब का विस्तार नहीं करता है।
    • [ ab = a? ]: a?ग्लोब फैलता है। तो वर्तमान निर्देशिका में फ़ाइलों के आधार पर सही या गलत हो सकता है।
    • [ ab = a\? ]: असत्य, ग्लोब विस्तार नहीं
    • =और ==दोनों में ही कर रहे हैं [और [[, लेकिन ==एक बैश विस्तार है।
    • case ab in (a?) echo match; esac: POSIX बराबर
    • [[ ab =~ 'ab?' ]]: झूठी 4 , के साथ जादू खो देता है''
    • [[ ab? =~ 'ab?' ]]: सच
  • =~

    • [[ ab =~ ab? ]]: सच है, POSIX ने नियमित अभिव्यक्ति मैच बढ़ाया , ?ग्लोब का विस्तार नहीं हुआ
    • [ a =~ a ]: वक्य रचना त्रुटि। कोई बैश के बराबर नहीं।
    • printf 'ab\n' | grep -Eq 'ab?': POSIX समतुल्य (केवल एकल पंक्ति डेटा)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX बराबर।

सिफ़ारिश : हमेशा उपयोग []

[[ ]]मेरे द्वारा देखे गए प्रत्येक निर्माण के लिए POSIX समकक्ष हैं ।

यदि आप का उपयोग करें [[ ]]:

  • पोर्टेबिलिटी खो देते हैं
  • पाठक को किसी अन्य बैश एक्सटेंशन की पेचीदगियों को सीखने के लिए मजबूर करें। [एक अजीब नाम के साथ सिर्फ एक नियमित आदेश है, कोई विशेष शब्दार्थ शामिल नहीं है।

¹ [[...]]कोर्न शेल में समतुल्य निर्माण से प्रेरित

² लेकिन के कुछ मूल्यों के लिए विफल रहता है aया b(जैसे +या index) और संख्यात्मक तुलना करता है, तो करता है aऔर bदशमलव पूर्णांकों की तरह लग रहे। expr "x$a" '<' "x$b"दोनों के आसपास काम करता है।

³ और यह भी के कुछ मूल्यों के लिए विफल रहता है aया bकी तरह !या (

4 बैश 3.2 और उससे अधिक में और बैश 3.1 के लिए अनुकूलता प्रदान की गई (सक्षम नहीं है BASH_COMPAT=3.1)

5 हालांकि समूहबद्धता (यहां {...;}कमांड समूह (...)जिसके साथ एक अनावश्यक उपधारा चलेंगे) आवश्यक नहीं है क्योंकि शेल ऑपरेटर ||और &&( ऑपरेटर ||और / ऑपरेटर के विपरीत ) समान पूर्वता रखते हैं। तो समकक्ष होगा।&& [[...]]-o-a [[ a = a ] || [ a = b ] && [ a = b ]


printf 'ab' | grep -Eq 'ab?'भीतर कैसे उपयोग करें if [ … ]?
meeDamian

1
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi[]एक आदेश की तरह है grep()कि आदेश पर की जरूरत नहीं किया जा सकता है मुझे यकीन है कि नहीं कर रहा हूँ: मैं इसकी वजह से जोड़ा |, कैसे बैश चीजों को पार्स करता है पर निर्भर करता है। अगर वहाँ नहीं था तो |मुझे यकीन है कि आप बस लिख सकते हैं if cmd arg arg; then
सिरो सेंटिल्ली 新疆 改造 i i

1
@ मीदीदामियन हाँ, इसकी कोई आवश्यकता नहीं ()लगती है: stackoverflow.com/questions/8965509/…
Ciro Santilli 新疆 ian ian 六四 '

1
अच्छी सूची! इन्हें भी देखें: wiki.ubuntu.com/…
रेडिस्टाओ

5

एकल ब्रैकेट यानी []एक सशर्त अभिव्यक्ति को संलग्न करने के लिए POSIX खोल अनुपालन है।

डबल ब्रैकेट्स यानी [[]]मानक POSIX संस्करण का वर्धित (या एक्सटेंशन) संस्करण है, यह बैश और अन्य गोले (zsh, ksh) द्वारा समर्थित है।

बैश में, अंकीय तुलना उपयोग हम के लिए eq, ne, ltऔर gtतुलना के लिए डबल कोष्ठक के साथ, हम उपयोग कर सकते हैं ==, !=, <,और >सचमुच।

  • [टेस्ट कमांड का एक पर्याय है। भले ही इसे शेल में बनाया गया हो, यह एक नई प्रक्रिया बनाता है।
  • [[ इसका एक नया उन्नत संस्करण है, जो एक कीवर्ड है, एक कार्यक्रम नहीं है।

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

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works

4

मैनपेज के प्रासंगिक अनुभाग की एक त्वरित पढ़ने के आधार पर, प्राथमिक अंतर प्रतीत होता है कि ==और !=वहाँ एक शाब्दिक स्ट्रिंग एक पैटर्न के खिलाफ ऑपरेटरों मैच के बजाय, और यह भी कि =~regex तुलना ऑपरेटर।

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