簡體   English   中英

使用簡單的Bash if / elif / else語句遇到麻煩

[英]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 ]

[將查看此內容,並意識到Thevalue都不是正確的參數,並且會抱怨。 使用引號可以防止這種情況:

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 

這樣,如果字符串是Darwin32Darwin64 ,則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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM