2013-02-23 89 views
1

我覺得自己像一個白癡。我需要一個BASH函數,每次調用它時都會交替出現值。腳本本身非常簡單,如果我直接調用該函數,它就可以工作。但是在一個字符串內部調用時它不起作用。代碼如下:BASH函數內部回顯字符串

odd_or_even() 
{ 
    if [ $ODDEVEN -eq 1 ]; then 
     echo "odd" 
     let "ODDEVEN+=1" 
    else 
     echo "even" 
     let "ODDEVEN-=1" 
    fi 
} 

ODDEVEN=1 
odd_or_even # Prints "odd" 
odd_or_even # Prints "even" 
echo "<td class=\"`odd_or_even`\">Test</td>" # Prints class=odd 
echo "<td class=\"`odd_or_even`\">Test</td>" # Prints class=odd 

BASH是否對字符串內部調用函數有限制?它似乎工作,因爲它輸出的東西,但它不執行數學運算。

回答

2

反引號創建子shell,並且環境在每個子shell中重置,因此實際上不會修改相同的變量ODDEVEN

您可以使用一個文件:

odd_or_even() 
{ 
    ODDEVEN=$(cat oddfile) 
    if [ $ODDEVEN -eq 1 ]; then 
    echo "odd" 
    let "ODDEVEN=0" 
    else 
    echo "even" 
    let "ODDEVEN=1" 
    fi 
    echo $ODDEVEN > oddfile 
} 

或者讓函數執行字符串操作:

odd_or_even() 
{ 
    prefix=$1 
    suffix=$2 
    if [ $ODDEVEN -eq 1 ]; then 
    out="odd" 
    let "ODDEVEN=0" 
    else 
    out="even" 
    let "ODDEVEN=1" 
    fi 
    echo $prefix$out$suffix 
} 

ODDEVEN=1 
odd_or_even "<td class=\"" "\">Test</td>" 
odd_or_even "<td class=\"" "\">Test</td>" 
0

目標的情況下這樣是讓功能出了子shell的。

function odd_or_even { 
    case $oddeven in 
     ?([01])) 
      typeset -a strings=(even odd) 
      printf %s "${strings[oddeven^=1]}" 
      ;; 
     *) return 1 
    esac 
} 

odd_or_even > >(echo "${prefix}$(</dev/fd/0)${suffix}") || exit 

既然你分配給非本地變量反正沒有真的不只是用它,而不是直接去擔心I/O的任何點。這將兩個部分都保留在子外殼之外。

oddeven= 
typeset -a strings=(even odd) 
echo "${prefix}${strings[oddeven^=1]}${suffix}" 

你原來的解決方案是隻有在ksh93t和mksh R41或更大可能使用不創建一個子shell特殊命令替換形式。

function odd_or_even { 
    ... 
} 

print -r -- "${prefix}${ odd_or_even;}${suffix}" 

順便說一句,Stop using backticks

1

也許不是最優雅的解決方案,但是您可以使用文件描述符,因爲它們被子進程(例如子殼)繼承。

正如已經指出的那樣,父級進程(父進程)不可見子進程(子進程)中的變量賦值(例如您的let "ODDEVEN+=1"let "ODDEVEN-=1")。

odd_or_even() 
{ 
    if [ $ODDEVEN -eq 1 ]; then 
     #echo "odd" 
     exec 3<&- 
     exec 3<<<"odd" 
     let "ODDEVEN+=1" 
    else 
     #echo "even" 
     exec 3<&- 
     exec 3<<<"even" 
     let "ODDEVEN-=1" 
    fi 
} 
export -f odd_or_even 

{ 
ODDEVEN=1 
odd_or_even && cat <&3 3<&- # Prints "odd" 
odd_or_even && cat <&3 3<&- # Prints "even" 
odd_or_even 
echo "<td class=\"`cat <&3 3<&-`\">Test</td>" # Prints class=odd 
odd_or_even 
echo "<td class=\"`cat <&3 3<&-`\">Test</td>" # Prints class=odd 
} 

# output: 
# odd 
# even 
# <td class="odd">Test</td> 
# <td class="even">Test</td>