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


161

मैं बैश उदाहरण पढ़ रहा हूँ, ifलेकिन कुछ उदाहरण एकल वर्ग कोष्ठक के साथ लिखे गए हैं:

if [ -f $param ]
then
  #...
fi

डबल वर्ग कोष्ठक के साथ अन्य:

if [[ $? -ne 0 ]]
then
    start looking for errors in yourlog
fi

अंतर क्या है?


3
आप इस प्रश्न का उत्तर देख कर अपना उत्तर प्राप्त कर सकते हैं: unix.stackexchange.com/questions/3831/…
अमीर

यह भी देखें serverfault.com/questions/52034/...
pevik

जवाबों:


188

सिंगल []पॉज़िक्स शेल कंप्लेंट कंडीशन टेस्ट हैं।

डबल [[]]मानक के लिए एक विस्तार []हैं और बैश और अन्य गोले (जैसे zsh, ksh) द्वारा समर्थित हैं। वे अतिरिक्त संचालन (साथ ही मानक पॉज़िक्स संचालन) का समर्थन करते हैं। उदाहरण के लिए: के ||बजाय -oऔर regex के साथ मिलान =~सशर्त निर्माणों पर बाश मैनुअल अनुभाग में मतभेदों की एक फुलर सूची पाई जा सकती है ।

का प्रयोग करें []जब भी आप अपनी स्क्रिप्ट के गोले भर में पोर्टेबल होना चाहता हूँ। [[]]यदि आप सशर्त अभिव्यक्ति का समर्थन नहीं करना चाहते हैं []और पोर्टेबल होने की आवश्यकता नहीं है, तो उपयोग करें ।


6
मुझे लगता है कि अगर आपकी स्क्रिप्ट एक शेलबैंग के साथ शुरू नहीं होती है, जो स्पष्ट रूप से एक शेल का समर्थन करने का अनुरोध करती है [[ ]](उदाहरण के साथ #!/bin/bashया #!/usr/bin/env bash), तो आपको पोर्टेबल विकल्प का उपयोग करना चाहिए। इस तरह के मान / बिन / श का समर्थन करने वाले लिपियों का हाल के डेबियन और उबंटू रिलीज जैसे ओएस पर टूट जाएगा जहां ऐसा नहीं है।
गॉर्डन डेविसन

87

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

बैश में परीक्षण 4.3.11:

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

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

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

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

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

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

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

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

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

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

  • <

  • && तथा ||

    • [[ a = a && b = b ]]: सत्य, तार्किक और
    • [ a = a && b = b ]: सिंटैक्स त्रुटि, &&एक AND कमांड विभाजक के रूप में पार्स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 हालांकि समूहीकरण (यहाँ के साथ {...;}आदेश समूह के बजाय (...)जो एक अनावश्यक subshell चल पाएंगे) नहीं के रूप में आवश्यक है ||और &&खोल ऑपरेटरों (के रूप में करने का विरोध किया ||और && [[...]]ऑपरेटर या -o/ -a [ऑपरेटरों) बराबर पूर्वता है। तो [ a = a ] || [ a = b ] && [ a = b ]समकक्ष होगा।


3
" हर [[]] निर्माण के लिए पोसिक्स समकक्ष हैं मैंने देखा है। " यही बात ग्रह के चेहरे पर किसी भी ट्यूरिंग पूर्ण भाषा के बारे में कहा जा सकता है।
ए। रिक

3
@ A.Rick कि सभी के लिए एक मान्य उत्तर होगा "भाषा में X कैसे करें Y" SO प्रश्न :-) बेशक, उस कथन में एक "सुविधाजनक" निहित है।
सिरो सेंटिल्ली 郝海东 冠状 i i 法轮功 '

6
शानदार सारांश। आपके परिश्रम के लिए धन्यवाद। मैं हालांकि सिफारिश से असहमत हूं। यह पोर्टेबिलिटी बनाम अधिक सुसंगत और शक्तिशाली वाक्य रचना है। यदि आपको अपने वातावरण में bash> 4 की आवश्यकता हो सकती है तो [[]] सिंटैक्स की सिफारिश की जाती है।
बर्नार्ड

@Downvoters कृपया समझाएं ताकि मैं जान सकूं और जानकारी में सुधार कर
सकूं

8
महान जवाब लेकिन मुझे लगता है कि सिफारिश : हमेशा उपयोग[] को मेरी प्राथमिकता के रूप में पढ़ा जाना चाहिए : []यदि आप पोर्टेबिलिटी नहीं खोना चाहते हैं तो उपयोग करें । जैसा कि यहां कहा गया है : यदि पोसिक्स या बॉर्नशेल के लिए पोर्टेबिलिटी / अनुरूपता एक चिंता का विषय है, तो पुराने सिंटैक्स का उपयोग किया जाना चाहिए। यदि दूसरी ओर स्क्रिप्ट के लिए BASH, Zsh या KornShell की आवश्यकता होती है, तो नया सिंटैक्स आमतौर पर अधिक लचीला होता है, लेकिन जरूरी नहीं कि पीछे की ओर संगत हो। मैं इसके बजाय जाऊँगा [[ ab =~ ab? ]]अगर मुझे पिछड़े अनुकूलता के बारे में कोई चिंता नहीं हैprintf 'ab' | grep -Eq 'ab?'
मॉरीशियोरोबायो

14

हालत परीक्षण (अर्थात [...]) के लिए एकल ब्रैकेट के अंदर, कुछ ऑपरेटर जैसे सिंगल =को सभी शेल द्वारा समर्थित किया जाता है, जबकि ऑपरेटर ==का उपयोग पुराने शेल में से कुछ द्वारा समर्थित नहीं है।

हालत परीक्षण (यानी [[...]]) के लिए डबल कोष्ठक के अंदर, वहाँ का उपयोग कर के बीच कोई अंतर नहीं है =या ==पुराने या नए गोले में।

संपादित करें: मुझे यह भी ध्यान देना चाहिए कि: बैश में, यदि संभव हो तो हमेशा डबल ब्रैकेट [[...]] का उपयोग करें, क्योंकि यह एकल ब्रैकेट की तुलना में अधिक सुरक्षित है। मैं उदाहरण के साथ क्यों उदाहरण देता हूँ:

if [ $var == "hello" ]; then

यदि $ var अशक्त / रिक्त होता है, तो यह वही है जो स्क्रिप्ट देखता है:

if [ == "hello" ]; then

जो आपकी स्क्रिप्ट को तोड़ देगा। इसका समाधान या तो डबल ब्रैकेट का उपयोग करना है, या हमेशा अपने चर के आसपास उद्धरण रखना याद रखें ( "$var")। डबल ब्रैकेट बेहतर रक्षात्मक कोडिंग अभ्यास है।


1
चारों ओर उद्धरण लाना चर के पढ़ता है जब तक आप एक है करने के लिए नहीं एक बहुत अच्छा कारण है बहुत , बेहतर बचाव की मुद्रा में कोडिंग अभ्यास के बाद से यह लागू होता है सभी चर की पढ़ता है, बस नहीं इन परिस्थितियों में। एक आईट्यून्स इंस्टॉलर बग ने एक बार लोगों की फ़ाइलों को हटा दिया यदि हार्ड ड्राइव नाम में रिक्त स्थान (या ऐसा कुछ) हो। यह आपके द्वारा बताई गई समस्या को भी हल करता है।
चाई टी। रेक्स


1

आप प्रकाश रेगेक्स मिलान के लिए डबल वर्ग कोष्ठक का उपयोग कर सकते हैं, जैसे:

if [[ $1 =~ "foo.*bar" ]] ; then

(जब तक आप bash का संस्करण प्रयोग कर रहे हैं, तब तक आप इस वाक्य रचना का समर्थन करते हैं)


6
सिवाय इसके कि आपने पैटर्न उद्धृत किया है, इसलिए अब इसे शाब्दिक स्ट्रिंग के रूप में माना जाता है।
ormaaj

बिल्कुल सच। कभी-कभी यह मुझे गुस्सा
दिलाता है

1

बैश मैनुअल कहते हैं:

जब [[, '<' और '>' संचालकों के साथ वर्तमान लोकेल का उपयोग करते हुए शब्दशः क्रमबद्ध किया जाता है। परीक्षण आदेश ASCII आदेश का उपयोग करता है।

(परीक्षण आदेश [] के समान है)

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