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


573

एक सह कार्यकर्ता एक कोड की समीक्षा में हाल ही में दावा किया है कि [[ ]]निर्माण से अधिक पसंद किया जा रहा है [ ]की तरह निर्माणों में

if [ "`id -nu`" = "$someuser" ] ; then 
     echo "I love you madly, $someuser"
fi

वह औचित्य प्रदान नहीं कर सका। वहाँ एक है?


19
लचीले बनें, कभी-कभी इसकी गहन व्याख्या की आवश्यकता के बिना अपने आप को एक सलाह सुनने की अनुमति दें :) जैसा कि इसके [[साथ कोड अच्छा और स्पष्ट है, लेकिन उस दिन को याद रखें जब आप सिस्टम पर अपने स्क्रिप्टवर्क को डिफ़ॉल्ट शेल के साथ पोर्ट करेंगे जो कि नहीं है , bashया kshआदि [बदसूरत, बोझिल है, लेकिन AK-47किसी भी स्थिति में काम करता है।
किश्ती

178
@rook आप एक गहरी व्याख्या के बिना एक सलाह सुन सकते हैं, निश्चित रूप से। लेकिन जब आप एक स्पष्टीकरण का अनुरोध करते हैं और नहीं मिलता है, तो यह आमतौर पर एक लाल झंडा होता है। "विश्वास करो, लेकिन सत्यापित करो" और वह सब।
जोसिप रॉडिन 11

6
यह भी देखें: बैश ऑपरेटरों के बीच क्या अंतर है [[बनाम [बनाम (बनाम? ( पर ? यूनिक्स और लिनक्स एसई।)।
codeforester

1
@rook दूसरे शब्दों में "जो आपके द्वारा कहा गया है उसे करें और प्रश्न न पूछें"
ग्लिफ़

@rook इसका कोई मतलब नहीं था।
रकीब

जवाबों:


606

[[कम आश्चर्य है और आमतौर पर उपयोग करने के लिए सुरक्षित है। लेकिन यह पोर्टेबल नहीं है - POSIX यह निर्दिष्ट नहीं करता है कि यह क्या करता है और केवल कुछ गोले इसका समर्थन करते हैं (बैश के बगल में, मैंने सुना है कि ksh भी इसका समर्थन करता है)। उदाहरण के लिए, आप कर सकते हैं

[[ -e $b ]]

यह जाँचने के लिए कि कोई फ़ाइल मौजूद है या नहीं। लेकिन साथ [, आपको उद्धृत करना होगा $b, क्योंकि यह तर्क को विभाजित करता है और चीजों को फैलता है जैसे "a*"(जहां [[यह शाब्दिक रूप से लेता है)। यह भी कि [बाहरी कार्यक्रम कैसे हो सकता है और हर दूसरे कार्यक्रम की तरह इसका तर्क भी सामान्य रूप से प्राप्त किया जा सकता है (हालाँकि यह एक बिल्डिन भी हो सकता है, लेकिन तब भी यह विशेष रूप से नहीं होता है)।

[[कुछ अन्य अच्छी विशेषताएं भी हैं, जैसे नियमित अभिव्यक्ति =~के साथ संचालकों के साथ मेल खाते हैं जैसे कि वे सी जैसी भाषाओं में जाने जाते हैं। यहाँ इसके बारे में एक अच्छा पृष्ठ है: परीक्षण [और , के बीच अंतर क्या है [[? और बैश टेस्ट


21
यह मानते हुए कि इन दिनों हर जगह बैश है, मुझे लगता है कि यह बहुत ही पोर्टेबल है। मेरे लिए एकमात्र सामान्य अपवाद बिजीबॉक्स प्लेटफ़ॉर्म पर है - लेकिन आप शायद इसके लिए एक विशेष प्रयास करना चाहते हैं, यह देखते हुए कि यह हार्डवेयर चलता है।
बंदूकें

14
@ गगन: वास्तव में। मेरा सुझाव है कि आपका दूसरा वाक्य आपके पहले को नापसंद करता है; यदि आप सॉफ़्टवेयर विकास को संपूर्ण मानते हैं, तो "बैश इज़ एवरीवन" और "अपवाद बिजीबॉक्स प्लेटफ़ॉर्म हैं" पूरी तरह से असंगत हैं। व्यस्त बॉक्स एम्बेडेड विकास के लिए व्यापक है।
ऑर्बिट में लाइटनेस दौड़

11
@ गैंस: भले ही मेरे बॉक्स पर बैश लगा हो, लेकिन यह स्क्रिप्ट को निष्पादित नहीं कर सकता है (मेरे पास कुछ डैश-वेरिएंट के समान / बिन / श हो सकता है, जैसा कि FreeBSD और Ubuntu पर मानक है)। बिजीबॉक्स के साथ अतिरिक्त अजीबता भी है: आजकल मानक संकलन विकल्पों के साथ, यह पार्स करता है, [[ ]]लेकिन इसे उसी तरह अर्थ देता है [ ]
डबियसजिम

59
@dubiousjim: यदि आप बैश-केवल कंस्ट्रक्शन (जैसे यह) का उपयोग करते हैं, तो आपके पास #! / बिन / बैश होना चाहिए, न कि #! / बिन / श।
निक मैटेओ

16
यही कारण है कि मैं अपनी स्क्रिप्ट का उपयोग करता हूं, #!/bin/shलेकिन फिर उन्हें उपयोग करने के लिए स्विच #!/bin/bashकरता हूं जैसे ही मैं कुछ बीओएस विशिष्ट सुविधा पर भरोसा करता हूं, यह संकेत देने के लिए कि यह बॉर्न शेल पोर्टेबल नहीं है।
एन्थोनी

151

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

बैश 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 समकक्ष ⁵
  • विस्तार और विभाजन (ग्लोब + ग्लोब) पर शब्द विभाजन और फ़ाइल नाम

    • 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?' ]]: false:, के साथ जादू खो देता है ''
    • [[ 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की तरह !या (

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

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


4
अच्छी व्याख्या। मैं [उन्हीं कारणों से उपयोग करता हूं ।
गॉर्डन

2
बाशसी में :) हा। POSIX के साथ छड़ी करने के लिए भेद और कारण का अच्छा स्पष्टीकरण।
जोनाथन कोमार

56

[[ ]]अधिक विशेषताएं हैं - मेरा सुझाव है कि आप अधिक जानकारी के लिए उन्नत बैश स्क्रिप्टिंग गाइड पर एक नज़र डालें , विशेष रूप से अध्याय 7. टेस्ट में विस्तारित कमांड कमांड अनुभाग ।

संयोग से, गाइड नोट्स के रूप में, [[ ]]ksh88 (कोर्न शेल के 1988 संस्करण) में पेश किया गया था।


5
यह एक बशीवाद से दूर है, इसे पहली बार कोर्न शेल में पेश किया गया था।
हेनक लैंगवेल्ड

6
@ थोमस, एबीएस को वास्तव में कई हलकों में बहुत खराब संदर्भ माना जाता है; हालांकि इसकी सटीक जानकारी का एक बड़ा हिस्सा है, यह अपने उदाहरणों में बुरी प्रथाओं को दिखाने से बचने के लिए बहुत कम देखभाल करता है, और अपने जीवन का एक बड़ा हिस्सा बिना सोचे समझे खर्च करता है।
चार्ल्स डफी

@CharlesDuffy आपकी टिप्पणी के लिए धन्यवाद, क्या आप एक अच्छा विकल्प नाम दे सकते हैं। मैं शेल स्क्रिप्टिंग का विशेषज्ञ नहीं हूं, मैं एक गाइड की तलाश में हूं, जो हर आधे साल में एक बार स्क्रिप्ट लिखने के लिए सलाह ले सकता है।
थॉमस

9
@ थोमस, वूलेज बशफा और संबंधित विकी वे हैं जो मैं उपयोग करता हूं; वे सक्रिय रूप से Freenode #bash चैनल (जो कभी-कभी कांटेदार होते हैं, शुद्धता के बारे में गहराई से ध्यान देने की प्रवृत्ति) के कारण होते हैं। BashFAQ # 31, mywiki.wooledge.org/BashFAQ/031 , इस प्रश्न के लिए सीधे प्रासंगिक पेज है।
चार्ल्स डफी

13

से कौन सा तुलनित्र, परीक्षण, कोष्ठक, या डबल ब्रैकेट, सबसे तेजी से है? ( http://bashcurescancer.com )

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

परीक्षण और एकल ब्रैकेट सबसे पोर्टेबल हैं क्योंकि वे अलग और बाहरी कमांड के रूप में मौजूद हैं। हालाँकि, यदि आपका BASH के किसी भी दूरस्थ आधुनिक संस्करण का उपयोग कर रहा है, तो डबल ब्रैकेट समर्थित है।


7
शेल स्क्रिप्ट में सबसे तेज़ के जुनून के साथ क्या है ? मैं चाहता हूं कि यह सबसे पोर्टेबल हो और जो सुधार [[ला सकता है उसके बारे में कम परवाह नहीं कर सकता है। लेकिन फिर, मैं एक पुराने स्कूल के पुराने गोज़ :-)
जेन्स

1
मुझे लगता है कि कई गोले निर्मित संस्करण साबित होते हैं [और testभले ही बाहरी संस्करण भी मौजूद हों।
डबियसजिम

4
@ सामान्य रूप से मैं सहमत हूं: लिपियों का पूरा उद्देश्य (है?) पोर्टेबिलिटी (अन्यथा, हम कोड और संकलन करेंगे, स्क्रिप्ट नहीं) ... दो अपवाद जो मैं सोच सकता हूं वे हैं: (1) टैब पूरा होना (जहां पूरा स्क्रिप्ट बहुत सशर्त तर्क के साथ वास्तव में लंबा हो सकता है); और (2) सुपर-प्रॉम्प्ट ( PS1=...crazy stuff...और / या $PROMPT_COMMAND); इन के लिए, मैं स्क्रिप्ट के निष्पादन में कोई बोधगम्य देरी नहीं चाहता ।
माइकल

1
सबसे तेजी से जुनून के कुछ बस शैली है। बाकी सभी समान हैं, तो अपनी डिफ़ॉल्ट शैली में अधिक कुशल कोड निर्माण को शामिल क्यों नहीं किया जाता है, खासकर अगर वह निर्माण भी अधिक पठनीयता प्रदान करता है? जहां तक ​​पोर्टेबिलिटी की बात है, तो बैश के लिए अनुकूल कई अच्छे कार्य स्वाभाविक रूप से गैर-पोर्टेबल हैं। उदाहरण के लिए, मुझे चलाने की आवश्यकता है apt-get updateअगर यह अंतिम चलाने के बाद से एक्स घंटे से अधिक हो। यह एक बड़ी राहत है जब कोई कोड के लिए बाधाओं की पहले से ही लंबी सूची से पोर्टेबिलिटी छोड़ सकता है।
रॉन बुर्क

5

यदि आप Google की शैली मार्गदर्शिका का अनुसरण कर रहे हैं :

टेस्ट, [और[[

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

# This ensures the string on the left is made up of characters in the
# alnum character class followed by the string name.
# Note that the RHS should not be quoted here.
# For the gory details, see
# E14 at https://tiswww.case.edu/php/chet/bash/FAQ
if [[ "filename" =~ ^[[:alnum:]]+name ]]; then
  echo "Match"
fi

# This matches the exact pattern "f*" (Does not match in this case)
if [[ "filename" == "f*" ]]; then
  echo "Match"
fi

# This gives a "too many arguments" error as f* is expanded to the
# contents of the current directory
if [ "filename" == f* ]; then
  echo "Match"
fi

1
Google ने लिखा है " नो पाथनाम एक्सपेंशन ... जगह लेता है " अभी तक [[ -d ~ ]]सही है (जिसका अर्थ है ~कि विस्तार किया गया था /home/user)। मुझे लगता है कि Google को लेखन में अधिक सटीक होना चाहिए था।
JamesThomasMoon1979

2

एक विशिष्ट स्थिति जहां आप उपयोग नहीं कर सकते हैं [[ऑटोटूलस कॉन्फ़िगर .ac स्क्रिप्ट में, कोष्ठक का एक विशेष और अलग अर्थ है, इसलिए आपको testइसके बजाय उपयोग करना होगा - [या [[ध्यान दें कि परीक्षण और [एक ही कार्यक्रम हैं।


2
यह देखते हुए कि ऑटोटूलस POSIX शेल नहीं है, आप कभी [POSIX शेल फ़ंक्शन के रूप में परिभाषित होने की उम्मीद क्यों करेंगे ?
गॉर्डन

क्योंकि ऑटोकॉन्फ़ स्क्रिप्ट शेल स्क्रिप्ट की तरह दिखती है, और यह एक शेल स्क्रिप्ट का उत्पादन करती है, और अधिकांश शेल कमांड इसके अंदर काम करते हैं।
vy32

-1

[[]] डबल ब्रैकेट्स सनोस के कुछ निश्चित संस्करण के तहत अनसुपोर्टेड हैं और फ़ंक्शन घोषणाओं के अंदर पूरी तरह से अनसुनी हैं: जीएनयू बैश, संस्करण २.०२.० (१) -राइज (स्पार्क-सन-सोलारिस २.६)


1
बहुत सच है, और बिल्कुल भी नहीं। पुराने संस्करणों में बैश पोर्टेबिलिटी पर विचार किया जाना चाहिए। लोग कहते हैं कि "बैश सर्वव्यापी और पोर्टेबल है, सिवाय इसके कि शायद (गूढ़ ओएस को यहां डालें) " - लेकिन मेरे अनुभव में, सोलारिस उन प्लेटफार्मों में से एक है जहां पोर्टेबिलिटी पर विशेष ध्यान दिया जाना चाहिए: न केवल पुराने बैश संस्करणों पर विचार करने के लिए नए OS, मुद्दों / बग w / सरणियाँ, कार्य, आदि; लेकिन यहां तक ​​कि उपयोगिताओं (लिपियों में प्रयुक्त) जैसे कि ट्र, सेड, ऑक, टार में विषमताएं और ख़ासियत हैं सोलारिस पर जिन्हें आपको काम करना है।
माइकल

2
आप सही कह रहे हैं ... सोलारिस पर इतनी अधिक उपयोगिताओं गैर पॉसिक्स, बस "डीएफ" आउटपुट और तर्कों को देखें ... शर्म की बात है सूर्य। उम्मीद है कि यह थोड़ा (कनाडा को छोड़कर) गायब हो रहा है।
मेहतर

7
सोलारिस 2.6 गंभीरता से? यह 1997 में जारी किया गया था और 2006 में समर्थन समाप्त कर दिया था। मुझे लगता है कि अगर आप अभी भी इसका उपयोग कर रहे हैं तो आपको अन्य समस्याएं हैं! संयोग से इसमें बैश v2.02 का उपयोग किया गया था, जो कि डबल ब्रैकेट पेश करता था, इसलिए उस पर भी उतना ही पुराना काम करना चाहिए। 2005 से सोलारिस 10 ने बैश 3.2.51 और 2011 से सोलारिस 11 बैश 4.1.11 का उपयोग किया।
पीटर

1
पुन: स्क्रिप्ट पोर्टेबिलिटी। लिनक्स सिस्टम पर आम तौर पर प्रत्येक उपकरण का केवल संस्करण होता है और वह GNU संस्करण होता है। सोलारिस पर आपके पास आमतौर पर सोलारिस-देशी संस्करण या जीएनयू संस्करण (जैसे सोलारिस टार बनाम जीएनयू टार) के बीच एक विकल्प होता है। यदि आप GNU विशिष्ट एक्सटेंशन पर निर्भर हैं, तो आपको यह बताना होगा कि आपकी स्क्रिप्ट में यह पोर्टेबल होना चाहिए। सोलारिस पर आप "g" के साथ उपसर्ग करते हैं, उदाहरण के लिए 'ggrep' यदि आप GNU grep चाहते हैं।
पीटर

-2

संक्षेप में, [[बेहतर है क्योंकि यह किसी अन्य प्रक्रिया को कांटा नहीं करता है। कोई भी ब्रैकेट या एकल ब्रैकेट डबल ब्रैकेट की तुलना में धीमा नहीं है क्योंकि यह एक और प्रक्रिया की तलाश में है।


8
टेस्ट और [बैश में एक ही बिलियन कमांड के लिए नाम हैं। type [यह देखने के लिए उपयोग करके देखें।
एबी

1
@alberge, यह सच है, लेकिन [[, से अलग है [, बैश कमांड-लाइन दुभाषिया द्वारा वाक्यविन्यास की व्याख्या की जाती है। बैश में, टाइप करने का प्रयास करें type [[। unix4linux सही है कि यद्यपि क्लासिक बॉर्न-शेल [परीक्षण सत्य मूल्य निर्धारित करने के लिए एक नई प्रक्रिया को छोड़ देता है, [[वाक्यविन्यास (बैश, zsh, आदि द्वारा ksh से उधार लिया गया) नहीं करता है।
टिम गिल्बर्ट

2
@ टिम, मुझे यकीन नहीं है कि आप किस बॉर्न शेल के बारे में बात कर रहे हैं, लेकिन [बिल-इन के साथ-साथ डैश ( /bin/shसभी डेबियन-व्युत्पन्न लिनक्स वितरण में) बनाया गया है।
एबी

1
ओह, मैं देख रहा हूं कि आपका क्या मतलब है, यह सच है। मैं पुराने सोलारिस या एचपी / यूएक्स सिस्टम पर / बिन / श की तरह कुछ सोच रहा था, लेकिन निश्चित रूप से अगर आपको उन लोगों के साथ संगत होने की आवश्यकता थी जो आप उपयोग नहीं करेंगे [[या तो।
टिम गिल्बर्ट

1
@alberge बॉर्न शेल बैश नहीं है (उर्फ बॉर्न अगेन शेल )।
कियमलुनो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.