2009-07-07 13 views
22

मैं एक साधारण खोल स्क्रिप्ट में दो तारों की तुलना करने की कोशिश कर रहा हूं। मैं /bin/bash के बजाय /bin/sh, और डिबगिंग के अनगिनत घंटे के बाद उपयोग कर रहा था, यह श (जो वास्तव में पानी का छींटा है) पता चला कोड के इस ब्लॉक को संभाल नहीं कर सकते हैं:बैश, डैश और स्ट्रिंग तुलना

if [ "$var" == "string" ] 
then 
    do something 
fi 

क्या एक पोर्टेबल तार तुलना करने के लिए रास्ता है /bin/sh का उपयोग कर? मुझे पता है कि मैं हमेशा उपयोग करके विपरीत कर सकता हूं! =, लेकिन मैं एक क्लीनर, पोर्टेबल तरीके के बारे में सोच रहा हूं।

+2

आप '[[$ var == "string"]]' का उपयोग कर सकते हैं, जो POSIX है, लेकिन वैकल्पिक (afaik)। या आप '[" $ var "=" string "]' का उपयोग करते हैं। सिंगल-ब्रैकेट संस्करण में चर के चारों ओर '' '' नोट करें: '$ var' खाली होने पर यह आवश्यक है –

+0

महत्वपूर्ण हिस्सा लीटब के रूप में' $ var' के आसपास उद्धरण है। उद्धरण के बिना, '[$ var = "value"] '' बन जाता है [= "मान"]' जो खोल को बहुत भयानक रूप से भ्रमित करता है। आपको शायद एक त्रुटि दिखाई देगी जैसे _ "[: =: यूनरी ऑपरेटर अपेक्षित" _ जब आपको अन्यथा रिक्त चर का सामना करना पड़ता है। –

+0

मैं "$ var" बनाम $ var के बारे में समझता हूं, मेरी समस्या == बनाम = – LiraNuna

उत्तर

32

dash एक बहुत सख्त पॉज़िक्स खोल है, यदि यह dash में काम करता है तो यह लगभग निश्चित है कि यह अन्य POSIX खोल में काम करेगा।

प्रयास करें:

if [ "$var" = "string" ] 
then 
    some_command 
fi 
8

क्यों एक संभावना है कि आपकी स्क्रिप्ट "गलत" खोल से चलाई जाएगी? मैं आप कर सकते सोच सकता है कि अपनी स्क्रिप्ट के शीर्ष पर मानक श-बैंग लाइन का उपयोग करके अपने उत्पाद के एक पूर्व-अपेक्षा: एक उपयोगकर्ता एक अलग खोल, अन्य गोले का उपयोग करता

#!/bin/bash 

यहां तक ​​कि अगर आम तौर पर अभी भी वहां हैं और यदि नहीं, तो बस शिकायत करें और बताएं कि वे एक प्री-रिक हैं।

ठीक उसी तरह से एक विशिष्ट कर्नेल स्तर, या अजीब अस्तित्व, एक पूर्व-रिकक हो सकता है।

अपने विशिष्ट प्रश्न के लिए, मेरा मानना ​​है कि दोनों sh और bash अनुमति देने के एक '=' स्ट्रिंग तुलना के लिए प्रयोग की जाने वाली - कि POSIX व्यवहार है:

if [ "a" = "a" ] ; then 
    echo yes 
fi 

yes 
+1

* "यहां तक ​​कि संभावना है कि आपकी स्क्रिप्ट" गलत "खोल से चलाई जाएगी?" * - क्या यह नियंत्रित करना संभव है कि ऑटोकॉन्फ़ द्वारा कौन सा खोल उपयोग किया जाता है? (यही कारण है कि मैं जवाब के लिए खोज रहा हूं) – jww

3

उपयोग = बजाय ==। तुलना परीक्षण (1) द्वारा संभाली जाती है। /usr/bin/[ आमतौर पर /usr/bin/test का एक लिंक है। केवल अंतर यह है कि यदि आप शेल स्क्रिप्ट में [ का उपयोग करते हैं, तो ] भी आवश्यक है।

ध्यान दें कि बैश में अंतर्निहित test/[ है, इसलिए यह वास्तव में /usr/bin/test का उपयोग नहीं करता है।

-3

आप awk

awk 'BEGIN{ 
string1="test" 
string2="tes1t" 
if(s1==s2){ 
    print "same string" 
}else{ 
    print "not same" 
} 
}' 
1

जवाब पहले से ही तैनात हैं निश्चित रूप से सही उपयोग कर सकते हैं, लेकिन यह सार्थक हो सकता है कि कभी-कभी पैरामीटर विस्तार नोट करने के लिए शायद के साथ इसी उद्देश्य को पूरा कर सकते हैं कुछ अतिरिक्त लचीलापन।

% p() { printf 'notvar = %b\n' "${notvar##"${string1}"}${string2}" ; } 
% string1='some stuff about things\c' 
% string2='some different stuff maybe' 
% notvar="$string1" p 
> 'some different stuff maybe' 
% notvar="$string2" p 
> 'some stuff about things' 

ठीक है, तो ऊपर सुपर उपयोगी है के रूप में नहीं है, लेकिन यह भी विचार है कि आप परीक्षण चर के लिए इसी तरह के तरीकों यहाँ-दस्तावेजों में, इन-लाइन चर असाइनमेंट यदि आवश्यक हो तो (एक हद तक उपयोग कर सकते हैं ...), या यहां तक ​​कि एक छोटा (और तेज़!) के रूप में भी आपका पहला बयान लिखने का मतलब है।

[ ! "${var##"string"}" ] && _MATCH || _NOMATCH 

या यहां तक ​​कि ...

[ ${#var#*"${s=string}"} -lt ${#var} ] && _SUB_STRING_TEST=TRUE 

संभवतः भी ...

% p() { printf '%s is %s of %s' "$2" "${var_chk-not}" "$1" 
> }<<HEREDOC 
> ${in="${1##*"${2}"*}"} 
> ${in:- 
>  ${in="${1##"${2}"}"} 
>  ${in:-${var_chk=all} 
>  ${var_chk=some} 
> } 
> HEREDOC 
% 
+1

यकीन नहीं है कि मैं इन तकनीकों का बड़ा लाभ नहीं देखता जबतक कि आप एक obfuscation प्रतियोगिता जीतने की कोशिश नहीं कर रहे हैं। – swdev