You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本仅在终端宽度变化时生成表格边框失效问题求助

问题描述

这段Bash脚本是每秒循环执行的一部分,目标是生成适配终端宽度的三列表格顶部边框:终端窗口大小变化时重新生成边框,宽度不变时直接复用之前生成的边框变量以提升绘制效率。但目前函数的else分支无法正常输出内容,变量似乎无法在下次循环中被保留,核心难点是需要用函数参数作为变量名存储边框,供后续循环读取。

核心问题分析
  1. 变量作用域问题:原脚本中用eval创建的变量默认是函数局部变量,循环每次调用函数时局部变量会被销毁,下次循环无法读取到之前存储的边框值;即使尝试过declare -g也被注释掉了,导致全局变量未成功创建。
  2. 初始值处理问题:第一次循环时term_width为空,term_width_previous没有被初始化,导致table_resized的判断逻辑在第一次执行时异常,后续循环的宽度对比也受影响。
修复方案

1. 确保边框变量为全局变量

替换原脚本中创建变量的代码,用declare -g直接创建全局变量,替代不安全的eval:

# 替换原有的eval或注释的declare行
declare -g "$border_id"="$border_value"

这样函数内部创建的变量会被提升到全局作用域,下次循环调用函数时能直接读取到之前存储的值。

2. 修正终端宽度的初始对比逻辑

在循环开始处初始化term_width_previous,避免第一次循环时变量为空:

# 初始化上一次终端宽度(第一次循环时用当前值)
term_width_previous=${term_width_previous:-$(tput cols)}
# 获取当前终端宽度
term_width=$(tput cols)
# 判断是否调整过大小
table_resized=$([ "$term_width" != "$term_width_previous" ] && echo "yes" || echo "no")

3. 优化边框生成效率(可选)

用printf的格式化功能替代循环生成重复字符,代码更简洁高效:
比如生成第一列横线可以改成:

border_value+=$(printf "%${col1_width}s" "" | tr ' ' '═')
修正后的完整脚本片段
# 初始化上一次终端宽度(第一次循环时用当前值)
term_width_previous=${term_width_previous:-$(tput cols)}

# 获取终端宽度
term_width=$(tput cols)

# 判断自上次循环后终端是否调整大小
table_resized=$([ "$term_width" != "$term_width_previous" ] && echo "yes" || echo "no")

# 根据终端宽度计算列宽
col1_width=16
col2_width=16
col3_width=$((term_width - col1_width - col2_width - 13))  # 13为填充和边框占用宽度
col4_width=10

# 语法:print_table_border "id" "左边框字符" "列文本或═"
print_table_border() {
    border_id=$1

    if [ "$table_resized" = "yes" ]; then
        border_value=""
        border_value+=$(printf " ")
        border_value+=$(printf "$2") ## 左边框
     
        # 第一列 - 显示文本或横线
        if [ "$3" = "═" ]; then
            # 用printf+tr替代循环生成横线
            border_value+=$(printf "%${col1_width}s" "" | tr ' ' '═')
        else
            col1_text=$3
            col1_text_length="${#col1_text}"
            border_value+=$(printf " $col1_text")
            # 计算剩余空格数并填充
            remaining_spaces=$((col1_width - col1_text_length - 1))
            border_value+=$(printf "%${remaining_spaces}s" "")
        fi

        border_value+=$(printf "$4")
        border_value+=$(printf "%${col2_width}s" "" | tr ' ' "$5")
        border_value+=$(printf "$6")
        # 第三列横线
        third_col_length=$((term_width - col1_width - col2_width - 6))
        border_value+=$(printf "%${third_col_length}s" "" | tr ' ' "$7")
        border_value+=$(printf "$8")
        border_value+=$(printf " \n")
        
        # 创建全局变量存储边框
        declare -g "$border_id"="$border_value"
        printf "%s" "${!border_id}"  # 打印生成的行

    else
        # 打印存储的全局变量内容
        printf "%s" "${!border_id}"  # 打印存储的行
    fi
}

print_table_border "sm_top_border" "╔" "═" "╦" "═" "╦" "═" "╗"

# 循环末尾更新上一次宽度
term_width_previous=$term_width

内容的提问来源于stack exchange,提问作者saltedlolly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:53:16