bash中嵌套的coprocess变量

时间:2016-01-03 14:59:41

标签: bash process multiprocessing background-process coproc

我想知道如何在coprocess中使用嵌套变量。例如,我可以通常以下列方式使用嵌套变量。

$ coproc a { while :;do echo lol;done; }
[1] 15827
$ b=a
$ read test <&${!b[0]}
$ echo $test
lol

但我不能为协同进程做这件事,至少在shell脚本中是这样做的:

#!/bin/bash

send_message() { echo "$2">$1; }
question() {
    TARGET="$1"
    echo "Why hello there.
Would you like some tea (y/n)?"
    read answer
    [[ $answer =~ ^([yY][eE][sS]|[yY])$ ]] && echo "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg" || echo "OK then."
    until [ "$SUCCESS" = "y" ] ;do
        send_keyboard "$TARGET" "Do you like Music?" "Yass!" "No"
        read answer
        case $answer in
            'Yass!') echo "Goody!";SUCCESS=y;;
            'No') echo "Well that's weird";SUCCESS=y;;
            *) SUCCESS=n;;
        esac
    done
}
startproc() {
    local copname="$1"
    local TARGET="$2"
    coproc $copname { question "$TARGET" 2>&1; }
    outproc "$copname" "$TARGET"
}
inproc() {
    local coproc="$1"
    shift
    echo "$@" >&"${!coproc[1]}"
}

outproc() {
    local coproc="$1"
    local TARGET="$2"
    while read -t 1 -u "${!coproc[0]}" line; do send_message "$TARGET" "$line"; done
}
startproc a test
inproc a y

这有效,但是这个

~ $ bash -vx t.sh
#!/bin/bash
send_message() { echo "$2">$1; }
question() {
        TARGET="$1"
        echo "Why hello there.
Would you like some tea (y/n)?"
        read answer
        [[ $answer =~ ^([yY][eE][sS]|[yY])$ ]] && echo "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg" || echo "OK then."
        until [ "$SUCCESS" = "y" ] ;do
                send_keyboard "$TARGET" "Do you like Music?" "Yass!" "No"
                read answer
                case $answer in
                        'Yass!') echo "Goody!";SUCCESS=y;;
                        'No') echo "Well that's weird";SUCCESS=y;;
                        *) SUCCESS=n;;
                esac
        done
}
startproc() {
        local copname="$1"
        local TARGET="$2"
        coproc $copname { question "$TARGET" 2>&1; }
        outproc "$copname" "$TARGET"
}
inproc() {
        local coproc="$1"
        shift
        echo "$@" >&"${!coproc[1]}"
}

outproc() {
        local coproc="$1"
        local TARGET="$2"
        while read -t 1 -u "${!coproc[0]}" line; do send_message "$TARGET" "$line"; done
}
startproc a test
+ startproc a test
+ local copname=a
+ local TARGET=test
+ outproc a test
+ local coproc=a
+ local TARGET=test
+ read -t 1 -u '' line
t.sh: line 34: read: : invalid file descriptor specificationinproc a y
+ inproc a y
+ local coproc=a
+ shift
+ echo y
t.sh: line 28: "${!coproc[1]}": Bad file descriptor
~ $ + question test

~ $

不:

DispatcherFactory::add('LocaleSelector');
ini_set('intl.default_locale', 'en_US');

提前致谢。

1 个答案:

答案 0 :(得分:1)

我找不到任何支持这种行为的文档,所以我倾向于认为这是一个错误。

coproc命令不会在

中展开$name
coproc $name COMMAND

因此,它最终会创建一个名为$name的协同工作数组。这不是一个合法的数组名称,但由于coproc工作的级别相对较低,因此它成功创建了数组。

例如:

$ echo $BASH_VERSION
4.3.11(1)-release
$ coproc $name { echo hello; }
[1] 23424
$ declare -p '$name'
declare -a $name='([0]="63" [1]="60")'
[1]+  Done                    coproc $name { echo hello; }

因此间接引用不起作用,因为coproc数组没有被调用,你认为它是什么。

我想你可以通过使用eval来解决这个问题,但是你需要在命令上获得正确引用的引用。我建议定义一个函数以使其更容易。

顺便说一句,在${!coproc[1]}中,下标[1]!之前应用,因此它表示“名称为${coproc[1]}的变量,而不是”元素名称为$coproc的数组中的1个。这适用于0因为${x}${x[0]}意味着完全相同的事情,无论x是标量还是(非关联)数组,但这确实是一种误导性的巧合。您需要在下划线的变量中包含下标:

cp1=$coproc[1]   # *Not* an array lookup, just a simple substitution
cmd >&${!cp1}