बैश में संख्याओं की तुलना


545

मैं बैश टर्मिनल के लिए स्क्रिप्ट लिखने के बारे में सीखना शुरू कर रहा हूं, लेकिन मैं यह काम नहीं कर सकता कि तुलनात्मक रूप से काम करने के तरीके को कैसे प्राप्त करूं। मेरे द्वारा उपयोग की जा रही स्क्रिप्ट है:

echo "enter two numbers";
read a b;

echo "a=$a";
echo "b=$b";

if [ $a \> $b ];
then 
    echo "a is greater than b";
else
    echo "b is greater than a";
fi;

समस्या यह है कि यह पहले अंक से संख्या की तुलना करता है, यानी 9 10 से बड़ा है, लेकिन 1 09 से अधिक है।

मैं सही तुलना करने के लिए संख्याओं को एक प्रकार में कैसे बदल सकता हूं?


1
बुनियादी पढ़ने: BashFAQ
douard लोपेज

6
बीटीडब्ल्यू, बाश में एक अर्ध-उपनिवेश एक बयान विभाजक है, न कि एक बयान टर्मिनेटर, जो एक नई-रेखा है। इसलिए यदि आपके पास एक लाइन पर केवल एक स्टेटमेंट है, तो ;एंड-ऑफ-लाइन सुपरफ्लस हैं। कोई नुकसान नहीं कर रहा है, बस कीस्ट्रोक्स की बर्बादी (जब तक कि आप अर्ध-कॉलोन टाइप करने का आनंदलें )।
cdarke

6
दशमलव में अग्रणी शून्य के साथ संख्या बाध्य करने के लिए: 10#$numberतो number=09; echo "$((10#$number))"इच्छा उत्पादन 9, जबकि echo $((number))उत्पादन करेगा एक त्रुटि "मूल्य भी आधार के लिए महान"।
अगली सूचना तक रोक दिया गया।

4
सभी उत्तर आपको बताते हैं कि क्या सही है, लेकिन क्या गलत नहीं है: आदेश >में ऑपरेटर क्या करता है [आदेश की तुलना करने के लिए दो तारों को क्रमबद्ध करना चाहिए, बजाय क्रम में वे संख्याओं के अनुसार क्रमबद्ध करेंगे। आप अधिक जानकारी पा सकते हैं man test
user3035772

जवाबों:


878

बैश में, आपको अंकगणित के संदर्भ में अपनी जाँच करनी चाहिए :

if (( a > b )); then
    ...
fi

POSIX गोले जो समर्थन नहीं करते हैं (()), आप उपयोग कर सकते हैं -ltऔर -gt

if [ "$a" -gt "$b" ]; then
    ...
fi

आप के साथ help testया तुलना ऑपरेटरों की पूरी सूची प्राप्त कर सकते हैं man test


7
जैसा कि @jordanm ने कहा "$a" -gt "$b"कि सही उत्तर है। यहां टेस्ट ऑपरेटर की एक अच्छी सूची है: टेस्ट कंस्ट्रक्शंस
जेफरी थॉमस

यह निश्चित रूप से काम कर रहा है, लेकिन मैं अभी भी प्राप्त कर रहा हूं "((: 09: मान के लिए बहुत बड़ा आधार है (त्रुटि टोकन" 09 "है)" अगर मैं 1 और 09 की तुलना करता हूं, लेकिन 01 और 09 नहीं है, जो अजीब है, लेकिन यह मूल रूप से हल हो गया है ! इसलिए धन्यवाद मेरी समस्या
advert2013

8
@ advert2013 आपको शून्य के साथ संख्याओं का उपसर्ग नहीं करना चाहिए। शून्य-पूर्व
-उप-

8
खबरदार है कि testजैसा एक कार्यक्रम है [। तो help testउस बारे में जानकारी देता है। यह जानने के लिए कि आपको कौन-सा बिल्ट-इन ( [[और (() help bashउस हिस्से का उपयोग और नेविगेट करना चाहिए ।
RedX

1
अंकगणितीय अभिव्यक्तियां महान हैं, लेकिन ऑपरेंड को अभिव्यक्ति के रूप में माना जाता है
x- यूरी

179

सादा और सरल

#!/bin/bash

a=2462620
b=2462620

if [ "$a" -eq "$b" ];then
  echo "They're equal";
fi

आप देख सकते हैं इस cheatsheet अगर आप बैश स्क्रिप्टिंग की अद्भुत दुनिया में अधिक संख्या comparsions चाहते हैं।

संक्षेप में, पूर्णांकों की तुलना केवल इसके साथ की जा सकती है:

-eq # equal
-ne # not equal
-lt # less than
-le # less than or equal
-gt # greater than
-ge # greater than or equal

मैं सिर्फ आपके अन्य बदलाव को दोहराता हूं - आसपास के दोहरे उद्धरण "$a"और "$b"कड़ाई से आवश्यक नहीं हैं लेकिन वे अच्छे अभ्यास हैं। घुंघराले ब्रेसिज़ यहाँ कुछ भी उपयोगी नहीं है।
टॉम फेनेच

1
महान चीटशीट, जिसे आपने लिंक किया था, उसे पहले नहीं मिला - अब बैश इतना जादू और अप्रत्याशित नहीं लगता - धन्यवाद!
इल्जा

क्या उद्धरण "अनिवार्य हैं या अभी [ $a -eq $b ]भी ठीक हैं?
derHugo

@derHugo उद्धरण वैकल्पिक हैं। गाइल्स के पास इस बारे में बेहतर व्याख्या है कि उन्हें कब
डैनियल आंद्रेई मिनकॉ


38

एक अच्छी बात यह भी है कि कुछ लोग जिनके बारे में नहीं जानते होंगे:

echo $(( a < b ? a : b ))

इस कोड की सबसे छोटी संख्या बाहर प्रिंट होगा aऔरb


5
यह सच नहीं है। bअगर छपेगा भी a == b
konsolebox

88
@konsolebox क्या यह सिर्फ मैं है, या 5 और 5 में से सबसे छोटी संख्या 5 है?
एलेक्स-डैनियल जकीमेंको-ए।

4
आपका कथन अस्पष्ट है। यहां तक ​​कि इस तरह एक कमांड पर आवेदन करना नहीं होगा:echo "The smaller number is $(( a < b ? a : b ))."
konsolebox

4
वह जो कह रहा है वह a < bअभी भी सच है अगर a == b। मुझे बश की हालत के बारे में सभी योनि नहीं पता है, लेकिन लगभग निश्चित रूप से ऐसी स्थितियां हैं जहां इससे फर्क पड़ेगा।
बिकुमुल

4
@ बिकम्यूल नहीं, वह ऐसा नहीं कह रहा है। यदि a == b, तो a < bझूठी का मूल्यांकन करता है, यही कारण है कि यह प्रिंट होगा b
मैप्सर्स

21

बैश में मैं ऐसा करना पसंद करता हूं क्योंकि यह एक सशर्त ऑपरेशन के रूप में खुद को अधिक संबोधित करता है (( ))जिसके उपयोग से अधिक अंकगणित होता है।

[[ N -gt M ]]

जब तक मैं जैसे जटिल सामान नहीं करता

(( (N + 1) > M ))

लेकिन हर किसी की अपनी प्राथमिकताएं होती हैं। दुख की बात यह है कि कुछ लोग अपने अनौपचारिक मानकों को लागू करते हैं।

अपडेट करें:

आप वास्तव में यह भी कर सकते हैं:

[[ 'N + 1' -gt M ]]

जो आपको कुछ और जोड़ने की अनुमति देता है जो आप [[ ]]अंकगणित सामान के अलावा कर सकते हैं ।


3
इसका अर्थ यह लगता है कि [[ ]]एक अंकगणित के संदर्भ को बल देता है (( )), जैसे कि जहाँ Nजैसा माना जाता है वैसा ही हो जाता है $N, लेकिन मुझे नहीं लगता कि यह सही है। या, अगर वह इरादा नहीं था, का उपयोग Nऔर Mभ्रामक है।
बेंजामिन डब्ल्यू।

@ BenjaminW.This को चेत की पुष्टि की आवश्यकता होगी, लेकिन -eq, -ne, -lt, -le -gt, और -ge "अंकगणितीय परीक्षण" (प्रलेखित) के रूप हैं जो यह अनुमान लगा सकते हैं कि ऑपरेंड अंकगणितीय अभिव्यक्तियों के अधीन हैं। अच्छी तरह से ..
konsolebox

इस पर वापस आने के लिए धन्यवाद, जैसा कि आप पूरी तरह से सही हैं और मैनुअल स्पष्ट रूप से यह बताता है: "जब [[कमांड के साथ उपयोग किया जाता है , Arg1और Arg2अंकगणितीय अभिव्यक्तियों के रूप में मूल्यांकन किया जाता है [...]"।
बेंजामिन डब्ल्यू।

मेरे पास है NUMBER=0.0; while [[ "$NUMBER" -lt "1.0" ]]; doऔर यह कहता हैbash: [[: 0.0: syntax error: invalid arithmetic operator (error token is ".0")
हारून फ्रेंक

@AaronFranke बैश अंकगणित दशमलव का समर्थन नहीं करता है।
konsolebox

6

यह कोड झांकियों की तुलना भी कर सकता है। यह awk (यह शुद्ध bash नहीं है) का उपयोग कर रहा है, हालांकि यह एक समस्या नहीं होनी चाहिए, क्योंकि awk एक मानक POSIX कमांड है जो कि आपके ऑपरेटिंग सिस्टम के साथ डिफ़ॉल्ट रूप से सबसे अधिक संभावना है।

$ awk 'BEGIN {return_code=(-1.2345 == -1.2345) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
0
$ awk 'BEGIN {return_code=(-1.2345 >= -1.2345) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
0
$ awk 'BEGIN {return_code=(-1.2345 < -1.2345) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
1
$ awk 'BEGIN {return_code=(-1.2345 < 2) ? 0 : 1; exit} END {exit return_code}'
$ echo $?
0
$ awk 'BEGIN {return_code=(-1.2345 > 2) ? 0 : 1; exit} END {exit return_code}'
$ echo $?

उपयोग के लिए इसे छोटा करने के लिए, इस फ़ंक्शन का उपयोग करें:

compare_nums()
{
   # Function to compare two numbers (float or integers) by using awk.
   # The function will not print anything, but it will return 0 (if the comparison is true) or 1
   # (if the comparison is false) exit codes, so it can be used directly in shell one liners.
   #############
   ### Usage ###
   ### Note that you have to enclose the comparison operator in quotes.
   #############
   # compare_nums 1 ">" 2 # returns false
   # compare_nums 1.23 "<=" 2 # returns true
   # compare_nums -1.238 "<=" -2 # returns false
   #############################################
   num1=$1
   op=$2
   num2=$3
   E_BADARGS=65

   # Make sure that the provided numbers are actually numbers.
   if ! [[ $num1 =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then >&2 echo "$num1 is not a number"; return $E_BADARGS; fi
   if ! [[ $num2 =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then >&2 echo "$num2 is not a number"; return $E_BADARGS; fi

   # If you want to print the exit code as well (instead of only returning it), uncomment
   # the awk line below and comment the uncommented one which is two lines below.
   #awk 'BEGIN {print return_code=('$num1' '$op' '$num2') ? 0 : 1; exit} END {exit return_code}'
   awk 'BEGIN {return_code=('$num1' '$op' '$num2') ? 0 : 1; exit} END {exit return_code}'
   return_code=$?
   return $return_code
}

$ compare_nums -1.2345 ">=" -1.2345 && echo true || echo false
true
$ compare_nums -1.2345 ">=" 23 && echo true || echo false
false

1
मैं बड़ी संख्या में काम कर रहा हूं और bashउनकी तुलना ठीक से करने की कोशिश नहीं कर रहा (कोशिश if (( 18446744073692774399 < 8589934592 )); then echo 'integer overflow'; fi)। awkएक आकर्षण की तरह काम करता है ( if awk "BEGIN {return_code=(18446744073692774399 > 8589934592) ? 0 : 1; exit} END {exit return_code}"; then echo 'no integer overflow'; fi)।
jaume

3

यदि आपके पास फ्लोट्स हैं, तो आप एक फ़ंक्शन लिख सकते हैं और फिर उस जैसे का उपयोग कर सकते हैं

#!/bin/bash

function float_gt() {
    perl -e "{if($1>$2){print 1} else {print 0}}"
}

x=3.14
y=5.20
if [ $(float_gt $x $y) == 1 ] ; then
    echo "do stuff with x"
else
    echo "do stuff with y"
fi

3

यदि आप फ्लोट नंबरों का उपयोग करना चाहते हैं तो ब्रैकेट सामान (जैसे, [[ $a -gt $b ]]या (( $a > $b ))) पर्याप्त नहीं है; यह एक सिंटैक्स त्रुटि की रिपोर्ट करेगा। यदि आप फ्लोट संख्या या फ्लोट संख्या की तुलना पूर्णांक से करना चाहते हैं, तो आप उपयोग कर सकते हैं (( $(bc <<< "...") ))

उदाहरण के लिए,

a=2.00
b=1

if (( $(bc <<<"$a > $b") )); then 
    echo "a is greater than b"
else
    echo "a is not greater than b"
fi

आप if स्टेटमेंट में एक से अधिक तुलना शामिल कर सकते हैं। उदाहरण के लिए,

a=2.
b=1
c=1.0000

if (( $(bc <<<"$b == $c && $b < $a") )); then 
    echo "b is equal to c but less than a"
else
    echo "b is either not equal to c and/or not less than a"
fi

यदि आप एक संख्यात्मक चर (पूर्णांक या नहीं) एक संख्यात्मक सीमा के भीतर हैं, तो यह जाँचना मददगार है।


यह मेरे लिए काम नहीं करता है। जहाँ तक मैं बता सकता हूँ, bc कमांड एक्जिट वैल्यू नहीं लौटाती है, बल्कि तुलनात्मक सही होने पर "1" प्रिंट करती है (और "0" अन्यथा)। मुझे इसके बजाय यह लिखना होगा:if [ "$(bc <<<"$a > $b") == "1" ]; then echo "a is greater than b; fi
टेरजे मिकाल

@TerjeMikal आपकी आज्ञा के लिए, क्या आपका मतलब है if [ $(bc <<<"$a > $b") == "1" ]; then echo "a is greater than b"; fi? (मुझे लगता है कि आपकी आज्ञा गलत लिखी गई थी।) यदि ऐसा है, तो यह भी काम करता है। बैश कैलकुलेटर (bc) कमांड एक बेसिक कैलकुलेटर कमांड है। कुछ और उपयोग उदाहरण यहाँ और यहाँ मिलते हैं । मुझे नहीं पता कि मेरे उदाहरण के आदेश ने आपके लिए काम क्यों नहीं किया।
नियंत्रण रेखा-डेटाविज्ञानी

2

मैंने इसे वर्जन स्ट्रिंग्स को सादे पूर्णांक मानों में परिवर्तित करने के लिए एक छोटे से फंक्शन का उपयोग करके हल किया, जिसकी तुलना की जा सकती है:

function versionToInt() {
  local IFS=.
  parts=($1)
  let val=1000000*parts[0]+1000*parts[1]+parts[2]
  echo $val
}

यह दो महत्वपूर्ण धारणाएं बनाता है:

  1. इनपुट एक " सामान्य सेमी वीर " है
  2. प्रत्येक भाग 0-999 के बीच है

उदाहरण के लिए

versionToInt 12.34.56  # --> 12034056
versionToInt 1.2.3     # -->  1002003

उदाहरण परीक्षण कि क्या npmकमांड न्यूनतम आवश्यकता को पूरा करती है ...

NPM_ACTUAL=$(versionToInt $(npm --version))  # Capture npm version
NPM_REQUIRED=$(versionToInt 4.3.0)           # Desired version
if [ $NPM_ACTUAL \< $NPM_REQUIRED ]; then
  echo "Please update to npm@latest"
  exit 1
fi

'सॉर्ट -वी' के साथ आप वर्जन नंबर को सॉर्ट कर सकते हैं और फिर तय कर सकते हैं कि उसे क्या करना है। आप इस तरह के फंक्शन की तुलना लिख ​​सकते हैं: function version_lt () {test "$ (printf '% s \ n' $" @। सॉर्ट -V | हेड -n 1) "==" $ 1 "; } और इसे इस तरह से उपयोग करें: अगर version_lt $ v1 $ v2; फिर ...
कोम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.