2017-04-23 91 views
1

我正在嘗試編寫一個讀取三個整數的腳本,然後檢查這些數字中的任意兩個的總和是否大於第三個。如果這是真的,那麼它檢查這些數字是否相等,並打印一條消息。如果不是,它檢查是否有任何兩個數字相等並打印另一條消息。如果以上所有都是錯誤的,它會打印一條消息,說明所有數字都不相同。 我試圖把在以下嵌套條件:Bash:if語句中的算術,比較和常規運算符的多個條件

read X 
read Y 
read Z 
if [ $X + $Y > $Z ] && [ $X + $Z > $Y ] && [ $Y + $Z > $X ] 
then 
    if [ $X = $Y = $Z ] 
    then 
     echo "All numbers are equal." 
    elif [ [ $X = $Y ] && [ $X != $Z ] ] || [ [ $X = $Z ] && [ $X != $Y ] ] || [ [ $Z = $Y ] && [ $X != $Y ] ] 
    then 
     echo "Two of the numbers are equal." 
    else 
     echo "None of the numbers is equal to another." 
    fi 
fi 

我已經嘗試了所有類型的括號,括號組合(以上只是其中之一),但他們都不至今工作。 我在相關的帖子已經採取一看:

Bash if statement with multiple conditions throws an error

Bash: Two conditions in if

How to represent multiple conditions in a shell if statement?

,但我還沒有發現任何被覆蓋在他們的算術運算符的條件。 任何人都可以告訴我什麼是正確的方式?

(編輯:我忘記在原帖中提到我是bash的新手,所以請原諒我可能犯的任何深刻的錯誤,我仍然在試圖弄清楚事情是如何工作的。)

+0

參見:'幫助test'。 '[']'是'test'內建的同義詞。 – Cyrus

+0

你在第一個'if'中意識到你只需要檢查兩個數字是否大於另一個,你不需要檢查每個組合。 – 123

+0

@ 123是的,你說得對,但我想在某個時候後,我更感興趣的是看看這樣的情況能否奏效以及如何實現。 – Ioannis

回答

3

下面是Inian的答案利用算術運算的一個變體,它不需要$來擴展變量,它們接受邏輯運算符,並且所有數字相等的第一個測試可以簡化下面的測試。

請注意,檢查值是否實際讀取爲整數是避免意外行爲的好主意。

#!/bin/bash 
read X 
read Y 
read Z 
if 
    ((X+Y>Z || X+Z>Y || Y+Z>X)) 
then 
    if 
    ((X==Y && Y==Z)) 
    then 
     echo "All numbers are equal" 
    elif 
    ((X==Y || X==Z || Z==Y)) 
    then 
    echo "Two of the numbers are equal" 
    else 
    echo "All three numbers are different" 
    fi 
fi 

$(())爲算術表達式擴展到內側的表達式的求值的結果。 (())用作一個命令,如果表達式是一個導致「真」值的測試,或者它的值爲非零數字,則返回0;否則返回非零值。這第二種形式對測試非常有用。

另外,我喜歡使用(())的屬性來處理腳本中的開/關選項。例如,如果變量爲空或0,((state_variable))將評估爲「假」,否則將評估爲「真」,其很好地映射到如何直觀地預期這樣的變量表現。

+0

這是一個很好的簡化OP的嘗試,試圖在我的答案中標記OP的邏輯,但是看起來很整潔! '++' – Inian

+0

你和@Inian都明白我的想法,但你離我最初想做的事更近一點。我想我用'(())'和'[[]]'混合了這兩種語法。你能否再次解釋一下你在代碼之後的第一段中描述的是什麼,(())作用是什麼?所以,如果我理解正確,如果它計算爲非零值,則返回0;如果計算爲0,則返回非零值?再次感謝你的幫助。 – Ioannis

+0

@Ioannis'(())'當它計算出一個數字時就會做你所說的,但如果它包含一個測試(即'==','!=','<'...),那麼它會返回' 0「,如果條件滿足,否則爲非零。從本質上講,它是一種不同類型的測試,可以像'[[]]'用於'if'/'while'語句中的條件以及任何其他地方使用命令的返回代碼。 – Fred

2

你也可以通過遞增匹配和使用case語句來以不同的方式做到這一點。

應該更容易用更多的變量進行縮放。

#!/bin/bash 

read X 
read Y 
read Z 

((Matches+=(X==Y))) 
((Matches+=(Y==Z))) 
((Matches+=(X==Z))) 

case "$Matches" in 

0) echo "None of the numbers is equal to another.";; 
1) echo "Two of the numbers are equal.";; 
3) echo "All numbers are equal.";; 

esac 
+1

你能解釋一下'((Matches + =(..))'部分在做什麼嗎?我對這種語法不熟悉。我猜它正在做類似@Cyrus的做法..?使用用戶提供的號碼創建一個數組?如果你有時間來解釋一下,我會很感激。再次感謝您的回答。 – Ioannis

+0

@Ioannis不僅僅是一個變量,它只是將條件'((X == Y))'的結果添加到''Matches''中,其中'1'爲'true','0'爲'false' 。然後我在case語句中檢查var中的值。 Cyrus的答案是使用關聯數組以及每個鍵必須是唯一的,所以當相同數字添加兩次時,數組中仍然只有一個鍵,然後他們只檢查數組中的鍵的數量。 – 123

+0

那麼,var'Matches'是否添加了每個測試的結果,而'0)1)3)'是否對應於var的值,並且相應地打印出消息? – Ioannis

1

一個完全不同的方法來解決問題。

#!/bin/bash 

declare -A a    # declare associative array a 

read x; a[$x]=$x 
read x; a[$x]=$x 
read x; a[$x]=$x 

case ${#a[@]} in 
    1) echo "All numbers are equal." ;; 
    2) echo "Two of the numbers are equal." ;; 
    3) echo "None of the numbers is equal to another." ;; 
esac 
+0

我真的不能說我明白你的腳本在做什麼。你讓我失望了一下。我想我或多或少地知道發生了什麼,但是能否請您更詳細地解釋語法?因爲第一個令人困惑,加上一些我不知道的運營商。我真的很感激。無論如何謝謝你的不同解決方案。我喜歡學習解決問題的新方法。 – Ioannis

+0

作爲介紹,我推薦一篇關於這個主題的文章[Associative Arrays](http://www.linuxjournal.com/content/bash-associative-arrays)。 – Cyrus

+0

如果只使用整數,則可以刪除'declare -A a'並使用普通數組。 – Cyrus

1

的一行功能,從123's answer凝結:

n=(No Two "" All) 
3a(){ echo "${n[$((($1==$2)+($1==$3)+($3==$2)))]} numbers are equal." ; } 

顯示所有三種情況:

3a 1 1 1 ; 3a 1 1 2 ; 3a 1 2 3 
All numbers are equal. 
Two numbers are equal. 
No numbers are equal.