POSIX兼容Shell环境下printf -v特性的等效实现方案咨询
POSIX兼容版Shell脚本修改方案
你原来的脚本用到了两个Bash专属特性(bashism),对应替换为POSIX标准语法即可实现兼容:
printf -v:Bash独有,用于直接给指定变量赋值,未纳入POSIX标准read -p:Bash独有,用于同时输出提示和读取输入,POSIX标准read无该参数
方案1:eval实现动态变量赋值(推荐,完全匹配原逻辑)
该方案和你原有脚本的调用逻辑完全一致,不需要调整外部调用方式:
#!/bin/sh prompt() { target_var="$1" while true; do # 提示信息输出到stderr,避免干扰标准输出 printf "Do you wish to install this program? " >&2 read ANSWER case "$ANSWER" in [Yy]* ) eval "$target_var=\"true\"" break ;; [Nn]* ) eval "$target_var=\"false\"" break ;; * ) echo "Please answer yes or no." >&2 ;; esac done } prompt "QUESTION" if [ "$QUESTION" = "true" ]; then echo "SUCCESS" elif [ "$QUESTION" = "false" ]; then echo "FAILURE" fi
说明
此处eval的写法完全安全:因为传入的目标变量名是脚本可控的固定值,不存在注入风险,执行时会先将$target_var替换为实际变量名(如QUESTION),最终等效执行QUESTION="true",和原printf -v效果完全一致。
方案2:命令替换捕获返回值(无eval)
如果你不想使用eval,可以通过命令替换捕获函数输出作为返回值,写法如下:
#!/bin/sh prompt() { while true; do printf "Do you wish to install this program? " >&2 read ANSWER case "$ANSWER" in [Yy]* ) echo "true"; break;; [Nn]* ) echo "false"; break;; * ) echo "Please answer yes or no." >&2;; esac done } # 捕获函数stdout输出赋值给变量 QUESTION=$(prompt) if [ "$QUESTION" = "true" ]; then echo "SUCCESS" elif [ "$QUESTION" = "false" ]; then echo "FAILURE" fi
说明
该方案需要注意:函数内所有用户提示、错误信息必须输出到stderr(加>&2),只有最终需要返回的结果输出到stdout,避免被命令替换捕获无关内容。
内容的提问来源于stack exchange,提问作者user15885911
相关产品推荐
相关产品推荐

