有没有办法从命令输出中读取行?

Mar*_*ton 9 shell io-redirection

我有一个预处理命令来输出文件

./preprocess.sh > preprocessed_file 
Run Code Online (Sandbox Code Playgroud)

并且preprocessed_file将像这样使用

while read line
do

    ./research.sh $line &

done < preprocessed_file 

rm -f preprocessed_file
Run Code Online (Sandbox Code Playgroud)

有什么方法可以将输出定向到while read line零件而不是输出到 preprocessed_file?我认为除了使用这个 temp 之外应该有更好的方法preprocessed_file

ctr*_*lor 17

是的!您可以使用流程管道|

./preprocess.sh |
    while IFS= read -r line
    do
        ./research.sh "$line" &
    done
Run Code Online (Sandbox Code Playgroud)

进程管道将一个进程的标准输出 ( stdout)传递到下一个进程的标准输入 ( stdin)。

您可以选择在 a 后面放置一个换行符|并将命令扩展到下一行。

注意:a|b等效于b < <(a),但没有魔法文件,并且以更易读的顺序,尤其是当管道变长时。

a|b|c 相当于 c < <(b < <(a))

a|b|c|d|ee < < (d < <(c < <(b < <(a))))

  • 注意:这个带有管道的解决方案的优点是比进程替换更具可移植性(一些 POSIX shell 不支持,比如 dash)。仍然考虑可移植性,管道的右侧*可能*在子shell中执行(这取决于shell),因此任何副作用(例如设置变量)可能不会影响shell脚本的环境。 (3认同)
  • "*`a|b` 等价于 `b &lt; &lt;(a)`*" - 接近,但不完全相同。在管道版本中,管道的两侧都在子shell中运行,而在进程替换版本中,只有被替换的进程在子shell中运行,但`a`在当前执行的shell级别范围内运行。这对 `a` 中设置的变量范围具有重要意义 (3认同)

cuo*_*glm 9

您可以使用 bash进程替换

while IFS= read -r line; do
  ./research.sh "$line" &
done < <(./preprocess.sh)
Run Code Online (Sandbox Code Playgroud)

进程替换的一些优点:

  • 无需保存临时文件。
  • 更好的性能。从另一个进程读取通常比写入磁盘更快,然后再读入。
  • 节省计算时间,因为它与参数和变量扩展、命令替换和算术扩展同时执行

  • 它不一定更快。因为当从管道读取时,“read”必须一次读取一个字节,而它可以通过读取更大的块来优化事物,并在读取常规文件时向后查找。最好是在可能的情况下首先完全避免“while read”循环。另请注意,您需要`IFS= read -r line` 将该行读入`$line`。在这里不加引号(调用 split+glob 运算符)可能没有意义。 (2认同)