Shell命令替换场景下函数返回值异常问题求助
Bash命令替换中函数无法更新变量的问题及解决
我编写了一个可在终端指定位置打印内容的函数print_in_specified_position,还实现了一个用于更新并返回新打印位置的函数get_new_line,但后者通过命令替换调用时无法返回正确值,始终返回初始值。想咨询是否可以通过将该函数作为参数传递的方式让代码正常工作?
相关代码
function print_in_specified_position() { local X="$1" local Y="$2" local STRING="$3" tput cup "$X" "$Y" printf "$STRING" } function show_script_options() { COLUMS=$(tput cols) LINES=$(tput lines) export PRINT_X=$(( COLUMS / 2 - 77 )) export PRINT_Y=$(( LINES / 2 - 11 )) if (( PRINT_X < 0 )); then PRINT_X=0 fi if (( PRINT_Y < 0 )); then PRINT_Y=0 fi function get_new_line() { PRINT_Y=$(( PRINT_Y + 1 )) echo $PRINT_Y } print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n → What do you want to do?\n" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n 1 - Option 1" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n 2 - Option 2" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n " print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n 3 - Option 3" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n 4 - Option 4" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n " print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n 5 - Option 5" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n " print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n 6 - Option 6" print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n " print_in_specified_position "$PRINT_X" "$(get_new_line)" "\n q - Quit\n" }
测试情况
- 单独调用
get_new_line时工作正常:
输出:get_new_line get_new_line get_new_line14 15 16 - 使用命令替换调用时失效:
输出:echo "$(get_new_line)" echo "$(get_new_line)" echo "$(get_new_line)"14 14 14 - 尝试
"$get_new_line"和"${get_new_line}"写法,均无效。
问题原因及解决方法
问题根源
命令替换$(...)会创建子shell执行内部命令,子shell会继承父shell的变量,但子shell内的变量修改不会同步回父shell。所以每次$(get_new_line)调用时,PRINT_Y的修改只在当前子shell中生效,父shell的PRINT_Y始终保持初始值,导致每次返回的都是同一个数。
有效解决方法(无需传递函数参数)
要让变量修改在当前shell生效,必须避免子shell。可以让get_new_line只负责更新变量,之后直接使用变量值:
function show_script_options() { COLUMS=$(tput cols) LINES=$(tput lines) PRINT_X=$(( COLUMS / 2 - 77 )) PRINT_Y=$(( LINES / 2 - 11 )) if (( PRINT_X < 0 )); then PRINT_X=0 fi if (( PRINT_Y < 0 )); then PRINT_Y=0 fi function get_new_line() { PRINT_Y=$(( PRINT_Y + 1 )) } get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n → What do you want to do?\n" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n 1 - Option 1" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n 2 - Option 2" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n " get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n 3 - Option 3" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n 4 - Option 4" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n " get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n 5 - Option 5" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n " get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n 6 - Option 6" get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n " get_new_line print_in_specified_position "$PRINT_X" "$PRINT_Y" "\n q - Quit\n" }
这里不需要export变量,因为所有操作都在同一个shell函数内完成。
关于函数参数传递的可行性
Bash中可以传递函数名作为参数,但本质上还是调用函数,只要使用命令替换就会触发子shell,无法解决变量同步问题。所以传递函数参数不是解决该问题的有效方案,核心还是要避免子shell对变量修改的隔离。
内容的提问来源于stack exchange,提问作者João Bonfim
相关产品推荐
相关产品推荐

