यह एक बहुत ही अस्पष्ट कोने का मामला है कि कोई एक बग पर विचार कर सकता है जिसमें परीक्षण [
अंतर्निहित है; हालाँकि, यह [
कई प्रणालियों पर उपलब्ध वास्तविक बाइनरी के व्यवहार से मेल खाता है । जहाँ तक मेरा बता सकते हैं, यह केवल कुछ मामलों और एक चर है कि एक से मेल खाता है एक मूल्य के होने को प्रभावित करता है [
की तरह ऑपरेटर (
, !
, =
, -e
, और इतने पर।
मुझे समझाएं कि क्यों, और कैसे इसके चारों ओर बैश और पोसिक्स गोले में काम करना है।
स्पष्टीकरण:
निम्नलिखित को धयान मे रखते हुए:
x="("
[ "$x" = "(" ] && echo yes || echo no
कोई बात नहीं; उपरोक्त पैदावार में कोई त्रुटि नहीं है, और आउटपुट yes
। इस तरह हम काम करने के लिए सामान की उम्मीद करते हैं। '1'
यदि आप चाहें तो तुलना स्ट्रिंग को बदल सकते हैं , और इसका मूल्य x
, और यह अपेक्षित रूप से काम करेगा।
ध्यान दें कि वास्तविक /usr/bin/[
बाइनरी उसी तरह व्यवहार करती है। यदि आप चलाते हैं जैसे '/usr/bin/[' '(' = '(' ']'
कि कोई त्रुटि नहीं है, क्योंकि कार्यक्रम यह पता लगा सकता है कि तर्क एकल स्ट्रिंग तुलना ऑपरेशन से मिलकर बनता है।
बग तब होता है जब हम और दूसरी अभिव्यक्ति के साथ। इससे कोई फर्क नहीं पड़ता कि दूसरी अभिव्यक्ति क्या है, जब तक यह वैध है। उदाहरण के लिए,
[ '1' = '1' ] && echo yes || echo no
आउटपुट yes
, और स्पष्ट रूप से एक वैध अभिव्यक्ति है; लेकिन, अगर हम दोनों को मिला दें,
[ "$x" = "(" -a '1' = '1' ] && echo yes || echo no
बैश अभिव्यक्ति को अस्वीकार कर देता है यदि और केवल अगर x
है (
या !
।
यदि हम वास्तविक [
कार्यक्रम का उपयोग करके ऊपर चला रहे थे , अर्थात
'/usr/bin/[' "$x" = "(" -a '1' = '1' ] && echo yes || echo no
त्रुटि समझ में आ जाएगी: चूंकि शेल परिवर्तनीय प्रतिस्थापन करता है, /usr/bin/[
बाइनरी केवल मापदंडों को प्राप्त करता है (
=
(
-a
1
=
1
और समाप्त करता है ]
, यह समझ में नहीं आता है कि क्या खुले कोष्ठक एक उप-अभिव्यक्ति शुरू करते हैं या नहीं, इसमें एक और ऑपरेशन शामिल है। निश्चित रूप से, इसे दो स्ट्रिंग तुलनाओं के रूप में पार्स करना संभव है, लेकिन इसे लालच के साथ ऐसा करना संभव है कि जब छोटे-छोटे उप-अभिव्यक्तियों के साथ उचित भावों को लागू किया जाए तो यह समस्या हो सकती है।
समस्या, वास्तव में, यह है कि शेल [
बिल्ट-इन उसी तरह से व्यवहार करता है, जैसे कि उसने x
अभिव्यक्ति की जांच करने से पहले मूल्य का विस्तार किया हो ।
(ये अस्पष्टताएं, और चर विस्तार से संबंधित अन्य, एक बड़ा कारण था कि बैश ने क्यों लागू किया और अब [[ ... ]]
इसके बजाय परीक्षण का उपयोग करने की अनुशंसा करता है ।)
वर्कअराउंड तुच्छ है, और अक्सर पुराने sh
गोले का उपयोग करके स्क्रिप्ट में देखा जाता है । आप एक "सुरक्षित" वर्ण जोड़ते हैं, अक्सर x
, स्ट्रिंग के सामने (दोनों मूल्यों की तुलना की जा रही है), यह सुनिश्चित करने के लिए कि अभिव्यक्ति एक स्ट्रिंग तुलना के रूप में पहचानी जाती है:
[ "x$x" = "x(" -a "x$y" = "x1" ]
[[ "$x" = '1' && "$y" = '1' ]]