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

基于Zenity的Bash脚本选项窗口重复弹出问题求助

问题原因与解决思路

问题根源

当你在select_letter对话框点击Cancel时,代码直接调用app_main()回到主菜单,但此时原来的select_letter函数并没有终止,它仍然留在函数调用栈中。当你再次选择“Analyze a Letter”并完成select_letter流程后,旧的调用栈会继续执行后续的select_letter_options,加上当前流程触发的select_letter_options,就导致了选项窗口弹出两次的问题——本质是递归调用引发的执行栈残留。

修复方案

移除子函数中直接调用app_main()的逻辑,改为通过返回值让上层的app_main控制流程,避免嵌套递归导致的执行栈混乱:

  1. 让select_letter和select_letter_options在用户取消时返回错误状态(非0值)
  2. 在app_main中检查子函数的返回状态,决定是否继续执行后续步骤

修改后的完整代码

#!/bin/bash

APP_NAME="bealeCrypter"

function select_letter () {
    letter=("FALSE" "1" "Treasury location" "none"
            "FALSE" "2" "Treasury contents" "yes"
            "FALSE" "3" "Treasury beneficiaries" "none")

    LETTER_FILES=$(zenity --list \
        --width=430 \
        --height=235 \
        --title="$APP_NAME" \
        --text="What letter do you want to $1 ?" \
        --checklist \
        --multiple \
        --column=Selection \
        --column=Letter \
        --column=Description \
        --column=Decrypted \
        "${letter[@]}")

    if [ $? -eq 0 ]; then
        if [ -z "$LETTER_FILES" ]; then
            select_letter "$1"
        fi
        return 0  # 正常选择完成,返回成功状态
    else
        return 1  # 用户取消,返回错误状态
    fi
}

function select_letter_options () {
    letter_options=("TRUE" "1" "Get the number of characters"
                    "TRUE" "2" "Get the smallest number"
                    "TRUE" "3" "Get the biggest number")

    LETTER_OPTIONS=$(zenity --list \
        --width=350 \
        --height=210 \
        --hide-header \
        --title="$APP_NAME" \
        --text="Choose the analyze letter options :" \
        --checklist \
        --multiple \
        --column=Selection \
        --column=Id \
        --column=Description \
        --hide-column=2 \
        "${letter_options[@]}")

    if [ $? -eq 0 ]; then
        if [ -z "$LETTER_OPTIONS" ]; then
            select_letter_options
        fi
        return 0  # 正常选择完成,返回成功状态
    else
        return 1  # 用户取消,返回错误状态
    fi
}

function app_main () {
    while true; do  # 用循环代替递归,避免栈溢出
        menu=("1" "Analyze a Letter")

        SELECTION=$(zenity --list \
            --width=350 \
            --height=210 \
            --hide-header \
            --title="$APP_NAME" \
            --text="What to do ?" \
            --column=Id \
            --column=Selection \
            --hide-column=1 \
            --cancel-label=Quit \
            "${menu[@]}")

        if [ $? -ne 0 ]; then
            exit 0
        fi

        case "$SELECTION" in
            1) 
                select_letter "analyze"
                if [ $? -eq 0 ]; then  # 只有select_letter正常完成,才调用选项函数
                    select_letter_options
                    echo -e "LETTER: $LETTER_FILES\nLETTER_OPTIONS: $LETTER_OPTIONS"
                fi
                ;;
            *) 
                continue
        esac
    done
}

app_main

关键修改说明

  • 子函数取消时不再调用app_main,而是返回1表示操作取消
  • app_main改用while true循环代替递归调用,避免递归栈积累
  • 调用select_letter后检查返回值,只有正常完成时才执行select_letter_options

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:24:18