Bash实现类Python生成器及解决生成值过量未消费问题
Bash 类Python生成器的实现与阻塞优化方案
初始实现思路
最初探索到的基于进程替换的类生成器写法结构如下:
#!/usr/bin/env bash { # 主代码,注意此处运行在主线程,使用管道实现则不具备该特性 ... IFS= read -d '' -r VALUE # 等价于Python中的next() ... } < <( # 字符串生成器 ... printf "%s\0" "$VALUE" # 等价于Python中的yield ... )
典型使用场景如下,该写法的核心优势是保持主逻辑简洁:
LINK_NAME="$DIR/$(basename "$FILE")" while [ -e "$LINK_NAME" ] && [ "$(readlink "$LINK_NAME")" != "$TARGET" ]; do IFS= read -d '' -r LINK_NAME done < <( printf "%s\0" "$DIR/Link to $(basename "$FILE")" printf "%s\0" "$DIR/Another link to $(basename "$FILE")" declare -i COUNT=3 while true; do case $COUNT in *1?) ORD="th";; *1) ORD="st";; *2) ORD="nd";; *3) ORD="rd";; *) ORD="th";; esac printf "%s\0" "$DIR/$COUNT$ORD link to $(basename "$FILE")" COUNT+=1 echo "[generated $COUNT]" >&2 # Debug ((COUNT>=100)) && break # 安全退出条件 done )
存在的问题
初始实现存在生成器预先生成大量超出实际需要的数值的问题,主程序运行速度越慢问题越明显。预期中printf输出未被消费时应当阻塞,但实际没有达到该效果。
尝试过对printf使用stdbuf -o0或stdbuf -oL关闭缓冲,没有生效。也无法对整个生成器使用stdbuf,因为它不是独立的可执行程序,同时也不希望将生成器拆分为单独文件破坏代码简洁性。
最终解决方案
通过coproc协同进程加两个工具函数的方式解决了阻塞问题,代码保持了较高的简洁度,实现如下:
#!/usr/bin/env bash yield() { read -r; printf "%s\0" "$*"; } next() { local _N _P="$1[1]"; echo >&"${!_P}"; _P="$1[0]"; IFS= read -d '' -r ${2-_N} <&"${!_P}"; (($#<2)) && echo -n "$_N"; } coproc generator ( ... yield "$VALUE" ... ) # 主代码 ... VALUE="$(next generator)" # 也可以使用该写法 next generator VALUE ...
内容的提问来源于stack exchange,提问作者User9123
相关产品推荐
相关产品推荐

