首页 > 解决方案 > 在不使用文件的情况下连续组合两个同时运行的 shell 命令的输出行

问题描述

我有两个应该同时运行的命令。当被某物触发时,它们都会输出一行文本。当其中一个输出某些内容时,我想连续打印格式化为单行的这些命令的输出。

例如,如果第一个命令输出(注释不是输出的一部分,只是它的顺序):

One   # 1
Two   # 5
Three # 6

第二个输出:

Aaa   # 2
Bbb   # 3
Ccc   # 4
Ddd   # 7

我想得到:

One -
One - Aaa
One - Bbb
One - Ccc
Two - Ccc
Three - Ccc
Three - Ddd

基本上,当任何命令输出一行时,我想用另一个命令输出的最后一行打印这一行,格式化。

我试图做这样的事情:

#!/bin/bash

out1=''
out2=''

output() { printf "%s - %s\n" "$out1" "$out2"; }

command1 | while read -r out1; do output; done &
command2 | while read -r out2; do output; done &

wait

但似乎并行 bash 函数无法访问全局变量,现在我考虑一下这是有道理的。通过将命令的输出重定向到文件来做到这一点很简单,但我不想不断地将数据写入磁盘。有没有办法在不使用文件的情况下做这样的事情?

PS 这些程序是i3statusakd。我想使用akd -p选项不断将当前键盘布局打印到标准输出,并将其与通常的 i3status 输出结合起来形成 i3bar 的状态

标签: bashshellconcurrencysh

解决方案


我想到了:

#!/bin/bash

layout=''
i3status=''

{ i3status & akd -p
} | while read -r line
do
    if [[ $line == * ]]; then
        i3status=$line
    else
        layout=$line
    fi
    printf "%s | %s\n" "$layout" "$i3status"
done

pkill -P $$

有一个小问题 - i3status 的输出变为无色,但我认为可以使用 JSON 输出修复。无论如何 - 这超出了这个问题的范围。感谢@markp-fuso 的建议。

PS 方括号内的不可打印字符是 font-awesome 的 wifi 符号。它始终是 i3status 输出的第一个字符,这就是我区分行的方式。另一种方法是使用字符串的长度 -akd -p总是打印两个字符并且i3status总是打印更多。


推荐阅读