我想将此命令重定向到一个变量:
{
printf 'scan on\n\n'
sleep 10
printf 'quit \n\n'
} | bluetoothctl
我尝试这样做:
variable=$(printf 'scan on\n\n' sleep 10 printf 'quit \n\n' | bluetoothctl)
echo $variable
但我得到空白输出。我也尝试过拆分它:
variable=$(printf 'scan on\n\n' | bluetoothctl)
sleep 10
printf 'quit \n\n'| bluetoothctl
echo $variable
但这次我只得到
Agent registered
[bluetooth]# quit
如何将stdout
运行时打印的第一个命令的输出重定向到变量中?
答案1
只是:
variable=$(
{
printf 'scan on\n\n'
sleep 10
printf 'quit \n\n'
} | bluetoothctl
)
命令替换的内部可以是任何 shell 代码1,并且不必位于一行。
在这里,您想要捕获整个管道的输出(实际上,这将是 的输出,bluetoothctl
因为所有其他命令的 stdout 都重定向到转到 的管道bluetoothctl
)。
您还可以使用以下命令捕获 only 的输出bluetoothctl
:
{
printf 'scan on\n\n'
sleep 10
printf 'quit \n\n'
} | variable=$(bluetoothctl)
但在 中bash
,要使其工作,您需要为最后一个管道组件设置选项lastpipe
(shopt -s lastpipe
,仅适用于非交互式 shell 实例)不是在子 shell 中运行。
然而,在这里,您不需要管道,您可以这样做:
variable=$(bluetoothctl --timeout 10 scan on)
如果要显示变量的内容,请记住语法是:
printf '%s\n' "$variable"
不是。echo $variable
有关详细信息,请访问:
这里的输出bluetoothctl
包含着色转义序列以及用于清除行内容的转义序列。如果不加引号$variable
,其内容将受到 split+glob 的影响,从而产生要传递到的随机单词列表,echo
该列表echo
将以空格分隔输出。所以你最终会把所有的东西都写在一行上,如果最后一个单词以 a 结尾清晰的线条序列(它在我的测试中所做的\r\e[K
:回车符接下来是清晰到生产线末端序列),你只会看到一个空行。
1 尽管有些 shellbash
用来阻塞带有不匹配括号的代码,例如当代码包含 case 语句case $x in foo)
或不平衡的注释时)
,shell 解析器将其误认为是)
关闭命令替换。
答案2
错误是缺少分号(否则相当于换行符)。如果您想查看输出的结构,请添加双引号。尝试:
variable=$( { printf 'scan on\n\n' ; sleep 10 ; printf 'quit \n\n' ; } | bluetoothctl)
echo "$variable"
答案3
一个可能的替代方案是一个简单的expect
脚本:
#!/usr/bin/expect
spawn bluetoothctl
send "scan on\r"
sleep 10
send "quit \r"
expect eof
\r
等于“返回/按 Enter”。制作可执行文件并运行。