我想将此命令重定向到一个变量:
{
printf 'scan on\n\n'
sleep 10
printf 'quit \n\n'
} | bluetoothctl
Run Code Online (Sandbox Code Playgroud)
我试图这样做:
variable=$(printf 'scan on\n\n' sleep 10 printf 'quit \n\n' | bluetoothctl)
echo $variable
Run Code Online (Sandbox Code Playgroud)
但我得到空白输出。我也尝试拆分它:
variable=$(printf 'scan on\n\n' | bluetoothctl)
sleep 10
printf 'quit \n\n'| bluetoothctl
echo $variable
Run Code Online (Sandbox Code Playgroud)
但这次我只得到
Agent registered
[bluetooth]# quit
Run Code Online (Sandbox Code Playgroud)
如何将stdout运行时打印的第一个命令的输出重定向到变量中?
只是:
variable=$(
{
printf 'scan on\n\n'
sleep 10
printf 'quit \n\n'
} | bluetoothctl
)
Run Code Online (Sandbox Code Playgroud)
命令替换的内部可以是任何 shell 代码¹,不必在一行上。
在这里,您想要捕获整个管道的输出(实际上,这将是 的输出,bluetoothctl因为所有其他命令都将其标准输出重定向到通向 的管道bluetoothctl)。
您还可以bluetoothctl仅使用以下命令捕获输出:
{
printf 'scan on\n\n'
sleep 10
printf 'quit \n\n'
} | variable=$(bluetoothctl)
Run Code Online (Sandbox Code Playgroud)
但是在 中bash,要使其工作,您需要设置lastpipe选项(shopt -s lastpipe,仅适用于非交互式 shell 实例),以使最后一个管道组件不在子 shell 中运行。
但是,在这里,您不需要管道,您可以这样做:
variable=$(bluetoothctl --timeout 10 scan on)
Run Code Online (Sandbox Code Playgroud)
如果要显示变量的内容,请记住语法是:
printf '%s\n' "$variable"
Run Code Online (Sandbox Code Playgroud)
不是。echo $variable
有关更多详细信息,请访问:
这里的输出bluetoothctl包含着色转义序列以及用于清除行内容的转义序列。如果你不加$variable引号,它的内容将受到 split+glob 的影响,导致一个随机的单词列表传递给echo它将echo以空格分隔输出。因此,您将在一行中结束所有内容,并且如果最后一个单词以清晰的序列结尾(它在我的测试中\r\e[K是这样做的:回车,然后是清除到行尾序列),你只会看到一个空行。
¹尽管一些 shell 包括bash用于扼杀带有不匹配括号的代码,例如当代码包含 case 语句case $x in foo)或不平衡的注释时),shell 解析器误认为)关闭命令替换。