2013-02-23 40 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>