![](/img/trans.png)
[英]Bash script with logical ands, and ors in an if elif else statement
[英]Having trouble with simple Bash if/elif/else statement
我正在編寫需要在Linux和Mac上都可以使用的bash腳本。
我正在編寫一個函數,該函數將根據所處的環境返回目錄路徑。
這是偽代碼:
如果我在Mac OS X機器上,則需要我的函數來返回路徑:
/usr/local/share/
否則,如果我在Linux機器上,則需要我的函數來返回路徑:
/home/share/
否則,您既沒有使用Linux也沒有使用Mac ...對不起。
我是Bash的新手,所以我為這個非常簡單的問題向您道歉。
下面是我編寫的函數。 無論是在Mac還是Linux上,它總是會返回
/usr/local/share/
請看一下,並以Bash的微妙之處啟發我。
function get_path(){
os_type=`uname`
if [ $os_type=="Darwin" ]; then
path="/usr/local/share/"
elif [ $os_type=="Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
echo $path
}
在測試命令中,操作符周圍需要空格: [ $os_type == "Darwin" ]
而不是[ $os_type=="Darwin" ]
。 實際上,您還應該使用=
而不是==
(雙等號是bashism,並且不適用於所有shell)。 另外, function
關鍵字也是非標准的,您應該將其保留。 同樣,您應該對變量引用(例如"$os_type"
)加雙引號,以防它們包含空格或任何其他有趣的字符。 最后,在標准輸出中回顯錯誤消息(“ ...不支持”)可能會使正在調用該函數的用戶感到困惑,因為它會出現在期望找到路徑的位置。 將其重定向到標准錯誤( >&2
)。 這是我清理后得到的結果:
get_path(){
os_type=`uname`
if [ "$os_type" = "Darwin" ]; then
path="/usr/local/share/"
elif [ "$os_type" = "Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported" >&2
exit 1
fi
echo "$path"
}
編輯:我對賦值和比較之間的區別的解釋太長了,無法發表評論,因此我在此處添加了它。 在許多語言中,有一種標准的表達式語法,當單獨使用它與在測試中使用時,它將是相同的。 例如,在C中,無論a = b
是單獨出現在一行上還是在if ( a = b )
這樣的上下文中, a = b
都可以執行相同的操作。 外殼不是那樣的-它的語法和語義根據確切的上下文而千差萬別,而上下文(而不是等號的數量)決定了含義。 這里有些例子:
a=b
本身就是一個賦值 a = b
本身將作為命令運行a
,並向其傳遞參數“ =”和“ b”。 [ a = b ]
使用參數“ a”,“ =“,“ b”和“]”運行[
命令(這是test
命令的同義詞)–它忽略“]”,並解析其他作為比較表達式。 [ a=b ]
也運行[
( test
)命令,但是這一次在刪除“]”之后,它只會看到一個參數“ a = b”-當給test
一個參數時,如果參數不是空白,而這個不是。 bash的內置版本[
( test
)接受==
作為=
的同義詞,但並非所有其他版本都支持。
順便說一句,只是為了使事情變得更復雜,bash還具有[[ ]]
表達式(如test
,但更簡潔,功能更強大)和(( ))
表達式(與其他事物完全不同),甚至還有( )
(運行它的內容作為命令,但在子外殼中)。
您需要了解[
意思。 最初,這是/bin/test
命令的同義詞。 這些是相同的:
if test -z "$foo"
then
echo "String '$foo' is null."
fi
if [ -z "$foo" ]
then
echo "String '$foo' is null."
fi
現在,您可以了解為什么所有參數都需要空格。 這些是參數 ,而不僅僅是布爾表達式。 實際上, 測試手冊頁是了解各種測試的好地方。 (注意: test
和[
是BASH shell的內置命令。)
if [ $os_type=="Darwin" ]
then
這應該是三個參數:
"$os_type"
=
而非==
"Darwin"
如果[“$操作系統類型” =“達爾文”]#三個參數到[
命令然后
如果使用單個方括號,則應該習慣於用引號將參數引起來。 否則,您將遇到麻煩:
foo="The value of FOO"
bar="The value of BAR"
if [ $foo != $bar ] #This won't work
then
...
在上面的代碼中,shell在評估表達式之前將其值插入$foo
和$bar
。 你會得到:
if [ The value of FOO != The value of BAR ]
[
將查看此內容,並意識到The
或value
都不是正確的參數,並且會抱怨。 使用引號可以防止這種情況:
if [ "$foo" != "$bar" ] #This will work
then
變成:
if [ "The value of FOO" != "The value of BAR" ]
這就是為什么強烈建議您在測試中使用雙方括號: [[ ... ]]
。 該測試在外殼程序對參數進行插值之前先檢查它們:
if [[ $foo = $bar ]] #This will work even without quotation marks
另外, [[ ... ]]
允許模式匹配:
if [[ $os_type = D* ]] # Single equals is supported
then
path="/usr/local/share/"
elif [[ $os_type == L* ]] # Double equals is also supported
then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
這樣,如果字符串是Darwin32
或Darwin64
,則if
語句仍然起作用。 再次注意,所有內容周圍都必須有空格,因為這些是命令的參數(實際上已經不復存在了,但這是Shell解析它們的方式)。
在條件的參數之間添加空格可解決此問題。
這有效
function get_path(){
os_type=`uname`
if [ $os_type == "Darwin" ]; then
path="/usr/local/share/"
elif [ $os_type == "Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
echo $path
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.