任何输入用尽后停止粘贴

时间:2014-05-01 19:04:31

标签: bash

我有两个程序在stdout上生成数据,我希望将paste输出放在一起。我可以成功地这样做:

paste <(./prog1) <(./prog2)

但是我发现这个方法会打印两个输入的所有行, 我真正想要的是在输入程序完成后停止paste

因此,如果./prog1产生输出:

a
b
c

./prog2产生:

Hello
World

我希望输出:

a Hello
b World

另请注意,其中一个输入程序实际上可能会产生无限输出,我希望能够处理这种情况。例如,如果我的输入是yes./prog2,我应该得到:

y Hello
y World

3 个答案:

答案 0 :(得分:3)

使用join代替Schwartzian transform

的变体
numbered () {
  nl -s- -ba -nrz
}
join -j 1 <(prog1 | numbered) <(prog2 | numbered) | sed 's/^[^-]*-//'

每行输入nl个数字,join -1 1将使用相同的数字加入相应的行。较长文件中的额外行将没有连接伙伴并被省略。完成join后,通过sed管道移除行号。

答案 1 :(得分:2)

考虑使用awk:

awk 'FNR==NR{a[++i]=$0;next} FNR>i{exit}
                   {print a[FNR], $0}' <(printf "hello\nworld\n") <(printf "a\nb\nc\n")
hello a
world b

将较长的输出生成程序作为第二个输入。

答案 2 :(得分:2)

这是一个解决方案:

while IFS= read -r -u7 a && IFS= read -r -u8 b; do echo "$a $b"; done 7<$file1 8<$file2

如果输入文件的最后一行没有以换行符终止(但这样的文件不是有效的文本文件),这会产生稍微烦人的效果。

你可以将它包装在一个函数中,当然:

paste_short() {
  (
    while IFS= read -r -u7 a && IFS= read -r -u8 b; do
      echo "$a $b"
    done
  ) 7<"$1" 8<"$2"
}