bash 中的嵌套协处理变量
Nested coprocess variable in bash
我想知道如何在coprocess.For示例中使用嵌套变量,我可以通过以下方式正常使用嵌套变量。
$ a=b
$ b=lol
$ echo ${!a}
lol
但我不能为协程执行此操作,至少在 shell 脚本中:
$ coproc a { while :;do echo lol;done; }
[1] 15827
$ b=a
$ read test <&${!b[0]}
$ echo $test
lol
这行得通,但是这个
#!/bin/bash
send_message() { echo "">; }
question() {
TARGET=""
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=""
local TARGET=""
coproc $copname { question "$TARGET" 2>&1; }
outproc "$copname" "$TARGET"
}
inproc() {
local coproc=""
shift
echo "$@" >&"${!coproc[1]}"
}
outproc() {
local coproc=""
local TARGET=""
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 "">; }
question() {
TARGET=""
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=""
local TARGET=""
coproc $copname { question "$TARGET" 2>&1; }
outproc "$copname" "$TARGET"
}
inproc() {
local coproc=""
shift
echo "$@" >&"${!coproc[1]}"
}
outproc() {
local coproc=""
local TARGET=""
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
~ $
提前致谢。
我找不到任何支持该行为的文档,所以我倾向于认为这是一个错误。
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。我建议定义一个函数以使其更容易。
顺便说一句,在${!coproc[1]}
中,下标[1]
被应用在!
之前,所以它意味着"the variable whose name is ${coproc[1]}
, rather than "数组的元素1,其名称是$coproc
。这适用于 0,因为 ${x}
和 ${x[0]}
表示完全相同的东西,无论 x
是标量还是 (non-associative) 数组,但这确实是一种误导巧合。您需要在要间接访问的变量中包含下标:
cp1=$coproc[1] # *Not* an array lookup, just a simple substitution
cmd >&${!cp1}
我想知道如何在coprocess.For示例中使用嵌套变量,我可以通过以下方式正常使用嵌套变量。
$ a=b
$ b=lol
$ echo ${!a}
lol
但我不能为协程执行此操作,至少在 shell 脚本中:
$ coproc a { while :;do echo lol;done; }
[1] 15827
$ b=a
$ read test <&${!b[0]}
$ echo $test
lol
这行得通,但是这个
#!/bin/bash
send_message() { echo "">; }
question() {
TARGET=""
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=""
local TARGET=""
coproc $copname { question "$TARGET" 2>&1; }
outproc "$copname" "$TARGET"
}
inproc() {
local coproc=""
shift
echo "$@" >&"${!coproc[1]}"
}
outproc() {
local coproc=""
local TARGET=""
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 "">; }
question() {
TARGET=""
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=""
local TARGET=""
coproc $copname { question "$TARGET" 2>&1; }
outproc "$copname" "$TARGET"
}
inproc() {
local coproc=""
shift
echo "$@" >&"${!coproc[1]}"
}
outproc() {
local coproc=""
local TARGET=""
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
~ $
提前致谢。
我找不到任何支持该行为的文档,所以我倾向于认为这是一个错误。
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。我建议定义一个函数以使其更容易。
顺便说一句,在${!coproc[1]}
中,下标[1]
被应用在!
之前,所以它意味着"the variable whose name is ${coproc[1]}
, rather than "数组的元素1,其名称是$coproc
。这适用于 0,因为 ${x}
和 ${x[0]}
表示完全相同的东西,无论 x
是标量还是 (non-associative) 数组,但这确实是一种误导巧合。您需要在要间接访问的变量中包含下标:
cp1=$coproc[1] # *Not* an array lookup, just a simple substitution
cmd >&${!cp1}