क्या एक चर या एक इंट के रूप में तुलना करते समय कोई बड़ा अंतर है


22

जिज्ञासा से बाहर, जब एक बैश वैरिएबल तुलना (इसका मूल्य a integer) किया जा रहा है, तो इसे कुछ पूर्वनिर्धारित मूल्य के खिलाफ या तो एक के रूप में घोषित किया जाना संभव intहै string

नमूना स्क्रिप्ट :

#!/bin/bash
f1()
{
        [ "$1" == "1" ] && echo "$FUNCNAME: \"1\" compared as string"
}

f2()
{
        [[ "$1" -eq 1 ]] && echo "$FUNCNAME: \"1\" compared as int"
}

f1 $1
f2 $1

आउटपुट :

$  ./param.sh 1
f1: "1" compared as string
f2: "1" compared as int

तथा

$  ./param.sh blah
$

दोनों फ़ंक्शन समान तरीके से व्यवहार करते हैं, और इसलिए मैं सोच रहा हूं कि क्या पूर्णांक चर की जांच करते समय पसंदीदा तरीका है? मैं जाँच के लिए जाना होगा intबनाम intके रूप में यह अधिक सख्त है, लेकिन मुझे आश्चर्य है कि किसी भी ड्रा के साथ यह कर पीठ देखते हैं अगर string?

इस मामले में, f2()तुलना के बारे में भी अधिक सख्त है, यानी एक दशमलव मान से गुजरने से यह टूट जाएगा, जबकि f1()इसे कोई समस्या नहीं होगी।


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

जवाबों:


18

हां, बहुत सारे मतभेद हैं। उदाहरण के लिए, =सटीक स्ट्रिंग समानता के लिए जाँच, लेकिन -eqसमानता के लिए जाँच करने से पहले अंकगणितीय दोनों भावों का मूल्यांकन करता है:

$ [ " 1 " -eq 1 ] && echo equal || echo not
equal
$ [ " 1 " = 1 ] && echo equal || echo not
not

$ [ +1 -eq 1 ] && echo equal || echo not
equal
$ [ +1 = 1 ] && echo equal || echo not
not

$ [ "0+1" -eq 1 ] && echo equal || echo not
equal
$ [ "0+1" = 1 ] && echo equal || echo not
not

इसके अलावा, खाली स्ट्रिंग शून्य के बराबर संख्यात्मक रूप से होती है:

$ [ "" -eq 0 ] && echo equal || echo not
equal
$ [ "" = 0 ] && echo equal || echo not
not

और जब आप तुलना करने वाले ऑपरेटरों को लाते हैं, तो एक पूरी अन्य श्रेणी का अंतर दिखाई देता है - उदाहरण के लिए, <बनाम पर विचार करना -lt:

$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not

ऐसा इसलिए है क्योंकि स्ट्रिंग "10" के बाद स्ट्रिंग "2" वर्णानुक्रम में है (क्योंकि 1 2 से पहले आता है), लेकिन संख्या "2" संख्या "10" की तुलना में संख्यात्मक रूप से कम है।


2
(( ... ))संख्यात्मक कार्यों के लिए भी मत भूलना । (( " 1 " == 1 )) && echo yes || echo noपरिणामyes
पैट्रिक

7

पूर्णांक बनाम स्ट्रिंग तुलना सबसे महत्वपूर्ण हो जाती है जब आप तुलनात्मक रूप से अधिक या उससे कम होते हैं:

#!/bin/bash

eleven=11
nine=9

[[ $nine < $eleven ]] && echo string   # fail

[[ "$nine" -lt "$eleven" ]] && echo integer # pass

पहला विफल हो जाता है क्योंकि 9 11 के बाद आता है जब लेक्सोग्राफिक रूप से क्रमबद्ध किया जाता है।

ध्यान दें कि उद्धरणों का उपयोग करना यह निर्धारित नहीं करता है कि आप तार या संख्या की तुलना कर रहे हैं, ऑपरेटर करता है। आप ऊपर दिए गए उद्धरण जोड़ या हटा सकते हैं, इससे कोई फर्क नहीं पड़ता। बैश डबल ब्रैकेट के भीतर अपरिभाषित चर पकड़ता है, इसलिए उद्धरण आवश्यक नहीं हैं। संख्यात्मक परीक्षणों के लिए एकल कोष्ठकों के साथ उद्धरणों का उपयोग करने से आप बचेंगे नहीं:

[ "" -lt 11 ]

वैसे भी एक त्रुटि है ("पूर्णांक अभिव्यक्ति की आवश्यकता है")। एकल ब्रैकेट में स्ट्रिंग तुलना के साथ उद्धरण एक प्रभावी सुरक्षा उपाय हैं:

[ "" \< 11 ]

भीतर नोट डबल कोष्ठक, ""होगा -eq 0लेकिन नहीं == 0


1
बैश में, डबल ब्रैकेट के भीतर चर को उद्धृत करना कड़ाई से आवश्यक नहीं है: बिलिन [[यह याद रखने के लिए पर्याप्त स्मार्ट है कि चर कहाँ हैं, और यह खाली चर द्वारा मूर्ख नहीं होगा। एकल कोष्ठक ( [) में यह सुविधा नहीं है, और उद्धरणों की आवश्यकता है।
बजे ग्लेन जैकमैन

@glennjackman ने गौर नहीं किया। [[ -lt 11 ]]एक त्रुटि है, लेकिन nothing=; [[ $nothing -lt 11 ]]नहीं है। मैंने पिछले पैराग्राफ को थोड़ा पीछे कर दिया है।
गोल्डिलॉक्स

2

इसके अतिरिक्त जो कहा गया है।
समानता के लिए तुलना संख्याओं के साथ तेज है, हालांकि शेल स्क्रिप्टिंग में यह दुर्लभ है कि आपको तेजी से गणना की आवश्यकता है।

$ b=234
$ time for ((a=1;a<1000000;a++)); do [[ $b = "234" ]]; done

real    0m13.008s
user    0m12.677s
sys 0m0.312s

$ time for ((a=1;a<1000000;a++)); do [[ $b -eq 234 ]]; done

real    0m10.266s
user    0m9.657s
sys 0m0.572s

यह देखते हुए कि वे अलग-अलग काम करते हैं, मैं कहूंगा कि प्रदर्शन अप्रासंगिक है - आपको उस चीज का उपयोग करने की आवश्यकता है जो आपको चाहिए।
१ly:

@godlygeek एक चर की समानता दोनों तरह से प्राप्त की जा सकती है। "-ईक्यू" तेज है।
इमैनुएल

वे समानता की विभिन्न परिभाषाओं के लिए परीक्षण करते हैं। यदि आप इस प्रश्न का उत्तर देना चाहते हैं "क्या यह चर सटीक स्ट्रिंग 123 को पकड़ता है", तो आप केवल उपयोग कर सकते हैं =, क्योंकि उपयोग करने से -eq"+123" के लिए भी मेल होगा। यदि आप जानना चाहते हैं "क्या यह चर, जब एक अंकगणितीय अभिव्यक्ति के रूप में मूल्यांकन किया जाता है, तो 123 के बराबर की तुलना करें", आप केवल उपयोग कर सकते हैं -eq। केवल समय मैं देख सकता हूं कि एक प्रोग्रामर को परवाह नहीं है कि समानता की कौन सी परिभाषा का उपयोग किया गया था, जब वह जानता है कि चर की सामग्री समय से पहले एक विशेष पैटर्न के लिए विवश हैं।
गॉडलीजेक

@godlygeek दिलचस्प है, सवाल संख्याओं की समानता की तुलना करने के बारे में था जैसे कि वे तार थे, क्या यह एक विशेष पैटर्न के लिए समय से पहले बाधित चर के मामले में फिट बैठता है?
इमैनुएल

आपका उदाहरण ( b=234) उस पैटर्न को फिट करता है - आप जानते हैं कि यह 13:4 या "234" या "233 + 1" नहीं है, क्योंकि आपने इसे स्वयं सौंपा है, इसलिए आप जानते हैं कि यह एक स्ट्रिंग के रूप में और एक संख्या के रूप में तुलना करना समान रूप से मान्य है। लेकिन ओपी की स्क्रिप्ट, चूंकि यह एक कमांड लाइन तर्क के रूप में इनपुट लेती है, इसलिए इसमें कोई बाधा नहीं है - इसे बुलावा ./param.sh 0+1./param.sh " 1"
मानें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.