在Bash管道中分块读取标准输入

3

我有一些使用管道的shell脚本,例如以下内容:

foo.sh | bar.sh

我的bar.sh调用了一些命令行程序,该程序只能处理特定数量的标准输入行。因此,我希望将foo.sh的大型标准输出分成N行,以进行多个bar.sh调用。本质上,对foo.sh的标准输出进行分页,并执行多个bar.sh
这是否可能?我希望在管道中间有一些魔法,就像foo.sh | ??? | bar.sh一样。 xargs -n并不能完全满足我的需求。

只能接收特定行数的标准输入的程序。您想如何处理管道中剩余的标准输入?要丢弃它吗?如果是,您可以尝试使用 head 命令。 - anishsane
2
他想要批量调用bar.sh处理多行数据。 - Barmar
2个回答

5

我没有机器来测试,但是您需要使用GNU Parallel使这更容易实现,大致如下:

foo.sh | parallel --pipe -N 10000 -k bar.sh

作为额外的奖励,它将并行运行与您拥有的CPU核心数量相同的许多bar.sh
如果您只想一次运行一个bar.sh,请添加-j 1
如果您想看到它会做什么但不执行任何操作,请添加--dry-run

1
使用 while read 循环。
foo.sh | while read line1 && read line2 && read line3; do
    printf "%s\n%s\n%s\n" "$line1" "$line2" "$line3" | bar.sh
done

对于较大的N,编写一个循环函数。
read_n_lines() {
    read -r line || return 1
    echo "$line"
    n=$(($1 - 1))
    while [[ $n -gt 0 ]] && read -r line; do
        echo "$line"
        n=$((n-1))
    done
}

然后你可以这样做:
n=20
foo.sh | while lines=$(read_n_lines $n); do
    printf "%s\n" "$lines" | bar.sh
done

这很接近了,但我的N是一个很大的数字,虽然可以编写一个带有N个谓词的while条件,但我宁愿不这样做。有没有可能不必编写N个谓词? - Stephen Chu
@StephenChu 我已经添加了一个函数,可以每次读取和回显N行。 - Barmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接