Ner*_*lek 6 linux bash zsh io-redirection
我正在寻找一个“元命令”xyz,这样:
(echo "foo"; echo "bar") | xyz rev
Run Code Online (Sandbox Code Playgroud)
将返回:
foo oof
bar rab
Run Code Online (Sandbox Code Playgroud)
我想避免使用临时文件,即我正在寻找比以下更简洁的解决方案:
tempfile=$(mktemp)
cat > $tempfile
cat $tempfile | rev | paste $tempfile -
Run Code Online (Sandbox Code Playgroud)
(当然,我想要一个通用的解决方案,对于任何命令,不仅仅是rev,您可以假设该命令为每个输入行只输出一行。)
Zsh 解决方案也是可以接受的。
一个壳函数。这将适用于任何支持<<<here-strings 的shell ,包括 zsh 和 bash。
xyz() {
while read line
do
printf "%s " "$line"
"$@" <<<"$line"
done
}
Run Code Online (Sandbox Code Playgroud)
$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab
Run Code Online (Sandbox Code Playgroud)
由于stdio缓冲的工作方式,在大多数情况下会出现很多问题。linux 的一种解决方法可能是使用该stdbuf程序并使用 coproc 运行命令,这样您就可以明确控制输出的交错。
下面假设命令在每一行输入后输出一行。
#!/bin/bash
coproc stdbuf -i0 -o0 "$@"
IFS=
while read -r in ; do
printf "%s " "$in"
printf "%s\n" "$in" >&${COPROC[1]}
read -r out <&${COPROC[0]}
printf "%s\n" "$out"
done
Run Code Online (Sandbox Code Playgroud)
如果需要更通用的解决方案,因为 OP 只要求程序的每一行输入最终输出一行而不是立即输出,则需要更复杂的方法。创建一个事件循环,read -t 0用于尝试从 stdin 和协进程读取,如果两者具有相同的“行号”,则输出,否则存储该行。如果在任何一轮事件循环中都没有准备好,为了避免使用 100% 的 cpu,然后在再次运行事件循环之前引入一个小的延迟。如果过程输出部分行,则存在额外的复杂性,这些需要缓冲。
如果需要这个更通用的解决方案,我会使用expect来编写它,因为它已经很好地支持处理多个输入流上的模式匹配。但是,这不是 bash/zsh 解决方案。
| 归档时间: |
|
| 查看次数: |
455 次 |
| 最近记录: |