0

我从 Bash 的手册页中学习了 Bash 进程替换。不幸的是,我对该功能的不熟练使用是丑陋的。

DEV=<(some commands that produce lines of data) && {
    while read -u ${DEV##*/} FIELD1 FIELD2 FIELD3; do
        some commands that consume the fields of a single line of data
    done
}

熟练的程序员还有其他方法可以做到这一点吗?

如果需要可执行示例,请尝试以下操作:

DEV=<(echo -ne "Cincinnati Hamilton Ohio\nAtlanta Fulton Georgia\n") && {
    while read -u ${DEV##*/} FIELD1 FIELD2 FIELD3; do
        echo "$FIELD1 lies in $FIELD2 County, $FIELD3."
    done
}

样本输出:

Cincinnati lies in Hamilton County, Ohio.
Atlanta lies in Fulton County, Georgia.

在我的实际应用中,“一些命令”比较复杂,但上面的示例抓住了问题的本质。

需要进程替换<()。流程替代的替代方案无济于事。

4

2 回答 2

3

使用 operator 重定向到循环的标准输入<

while read city county state; do
    echo "$city lies in $county County, $state."
done < <(echo -ne "Cincinnati Hamilton Ohio\nAtlanta Fulton Georgia\n")

输出:

Cincinnati lies in Hamilton County, Ohio.
Atlanta lies in Fulton County, Georgia.

请注意,在此示例中,管道也可以正常工作。

echo -ne "Cincinnati Hamilton Ohio\nAtlanta Fulton Georgia\n" |
    while read city county state
do
    echo "$city lies in $county County, $state."
done

此外,应为环境变量(如PATH)和其他特殊变量(如RANDOM)保留大写变量名。描述性变量名称总是好的。

于 2019-11-23T19:08:12.073 回答
1

可移植的替代品很少。“正确”的选择取决于具体情况。特别是,它取决于生成输入数据的时间和输入的大小。尤其:

  • 如果处理数据需要大量时间,您希望在数据生成和“while”循环之间进行并行处理。这将导致增量处理,并且在开始输出数据处理之前不必等待所有输入数据处理。

  • 如果输入非常大(并且不适合 shell 变量),您可能别无选择,只能强制使用实际管道。当数据是二进制、Unicode 或类似数据时也是如此——其中 bash 变量将不起作用。

映射到原始问题 - PRODUCE = echoCincinnati ...和 CONSUME -echo "$city ..."

对于琐碎的情况(小输入,快速生产/消费),以下将起作用。Bash 将依次运行它们:先生产然后再消费。

while read ... ; do
    CONSUME
done <<< "$(PRODUCE)"

对于复杂的情况(输入量大,或者生产消耗慢),可以使用以下方式请求并行执行

while read ... ; do
    CONSUME
done < <(PRODUCE)

对于 PRODUCE 代码很复杂(循环、条件等)或很长(多行),请考虑将其移动到函数中,而不是将它们内联到循环命令中。

function produce {
    PRODUCE
}

while read ... ; do
    CONSUME
done < <(produce)
于 2019-11-23T19:20:18.273 回答