2011-07-29 63 views
6

考慮這個(示例性)bash腳本:如果我在Cygwin的bash的運行它遞增變量觸發EXIT在bash 4,但不是在bash 3

#!/bin/bash -e 
errorExit() { 
    echo "" >&2 
    echo "ERROR (${var_scriptfilename}):" >&2 
    echo "An unhandled error occurred." >&2 
    intentionalExit 1 
} 
intentionalExit() { 
    trap - EXIT # Unregister the EXIT trap 
    exit $1 
} 
trap errorExit EXIT # Trap script errors 
var_scriptfilename="$(basename "$0")" 
# ==== START OF TEST ==== 
var_counter=0 
((var_counter++)) 
echo "var_counter is $var_counter" >&2 
# ===== END OF TEST ===== 
intentionalExit 0 

它產生期望的輸出:

var_counter is 1 

不過,如果我對我的Debian擠壓盒,這是它的預期目的運行它,我在出口俘獲結束:

ERROR (test.increment.sh): 
An unhandled error occurred. 

...爲什麼呢?

如果我刪除了-e選項,它在兩個系統上都按預期工作,但顯然我想保留-e。

稍微更繁瑣的「通用」變體var_counter=$(($var_counter+1))適用於兩個shell都設置的-e,但我更喜歡使用第一個符號(或類似的外觀),因爲它明顯作爲增量操作突出顯示閱讀代碼時。

在Cygwin的bash的bash --version說:

GNU bash, version 3.2.51(24)-release (i686-pc-cygwin) 
Copyright (C) 2007 Free Software Foundation, Inc. 

Debian的,那就是:

GNU bash, Version 4.1.5(1)-release (x86_64-pc-linux-gnu) 
Copyright (C) 2009 Free Software Foundation, Inc. 

我好奇,爲什麼這是這樣。有人知道這種行爲的原因嗎?

此外,有沒有人知道類似的方式來增加一個變量在bash中,我可以使用?

+1

當你設置-vx時,你看到任何有用的東西嗎?祝你好運。 – shellter

回答

9

從Debian上的bash4手冊頁:

((expression)) 
    The expression is evaluated according to the rules described 
    below under ARITHMETIC EVALUATION. If the value of the expres‐ 
    sion is non-zero, the return status is 0; otherwise the return 
    status is 1. This is exactly equivalent to let "expression". 

,也...

-e  Exit immediately if a pipeline (which may consist of a 
     single simple command), a subshell command enclosed in 
     parentheses, or one of the commands executed as part of 
     a command list enclosed by braces (see SHELL GRAMMAR 
     above) exits with a non-zero status. 

所以發生的是((var++))增量VAR從0到1,然後返回 0,從而導致整體表達式返回非零,這會觸發 errexit

現在針對兩個不同bash版本之間的區別:這個變化 在((行爲似乎已經發生在4.0和4.1之間。在4.0 (( 顯然沒有觸發errexit。有關詳細信息,請參閱此NEWS文件。 你必須向下滾動到135行左右。來自 分佈的Changelog似乎證實了這一點。

如果您只想在不使用退出狀態的情況下增加一個變量,則可以使用多種方法來執行此操作。也許一些人會提出建議 上是最好的,但有些可能是:

  • var="$((var+1))",便攜式POSIX sh方法
  • ((var++)) || true,迫使語句始終有一個零種 退出狀態(慶典只有)
+0

非常感謝,那肯定會給你帶來很多亮點。我認爲,EXIT只是因爲我從0開始計數,所以我可以使用前增量而不是後增量,即'((++ var_counter))'而不是'((var_counter ++))''。計算結果從1開始,返回值始終爲零。我已經成功地在現在提到的兩個shell上測試了這個。 – eomanis

+1

很好的解釋。 $((和(不同)?(不同的?) –

+2

@FelipeAlvarez'(())'是一個獨立的命令,就像在其他編程語言中執行一個語句一樣,'((2 + 2))'會運行,返回0 '$(())'是一個擴展 - 表達式的結果被插入到命令行而不是'$(())'表達式中。它通常用作較長命令行的一部分。 – jw013