Bash支持yes/no/cancel的交互式提示函数开发求助
Hey there! Let's get that ask function working properly for you. I see you're running into issues with set -e compatibility and the cancel behavior—let's walk through a solution that checks all your boxes.
Fixed
ask Function ask() { local prompt="$1" local default="y" # Adjust default to "n" if needed while true; do # Show prompt with options read -p "$prompt [Y/n/c] " answer # Handle empty input with default value if [[ -z "$answer" ]]; then answer="$default" fi # Normalize input to lowercase for consistent matching local lower_answer=$(echo "$answer" | tr '[:upper:]' '[:lower:]') case "$lower_answer" in y|yes) echo "true" return 0 ;; n|no) echo "false" return 1 ;; c|cancel) echo "Aborting script..." >&2 # Terminate the entire script, whether in main shell or subshell if [[ "$BASHPID" -eq "$$" ]]; then # Running directly in main shell—exit immediately exit 1 else # Running in subshell (variable assignment)—kill main script kill -SIGTERM "$$" exit 1 fi ;; *) echo "Invalid input! Please enter y/yes, n/no, or c/cancel." >&2 ;; esac done }
How This Meets Your Requirements
Let's break down how this function addresses every need you listed:
- Accepts question as parameter: Uses
$1to capture your prompt text. - Supports [y/n/c] and case variants: Converts input to lowercase, so
Y,YES,N,Cancelall work as expected. - Returns correct values for yes/no: Outputs
"true"/return 0for yes (works withifstatements) and"false"/return 1for no (triggerselsebranches). - Works with variable assignment or
ifstatements:- Use in
if:if ask "Are you happy?"; then echo "Awesome!"; fi - Assign to variable:
answer=$(ask "Save changes?")
- Use in
- Cancel terminates the entire script: Checks if it's running in the main shell or a subshell (from variable assignment) and ensures the whole script stops either way.
- Retries on invalid input: Loops until a valid answer is given.
- Empty input uses default: Falls back to the
defaultvariable (set to "y" here, easy to change). - Compatible with
set -eandset +e:- In
set -emode,return 1for no doesn't crash the script because it's either in anifcondition (a "tested" command thatset -eignores) or part of a variable assignment (which has a success exit code regardless of the command inside). - Cancel works reliably in both modes, as it directly terminates the script.
- In
Usage Examples
1. Using with if Statement (works with set -e)
set -e if ask "Ready to start the deployment?"; then echo "Initiating deployment..." # Add your deployment commands here else echo "Deployment cancelled by user." fi
2. Assigning to a Variable (works with set +e)
set +e answer=$(ask "Do you want to delete temporary files?") if [[ "$answer" == "true" ]]; then rm -rf /tmp/temp_files/ echo "Temporary files deleted." else echo "Temporary files retained." fi
3. Testing Cancel
Try entering c or Cancel in either of the above examples—your entire script will terminate immediately, as expected.
What Was Wrong With the Original Code?
- Cancel only worked in main shell: The original
exit 1would only terminate a subshell (when using variable assignment) instead of the whole script. Our fix checks the execution context and kills the main script if needed. set -ecrashes on "no": Whileset -edoesn't trigger onifconditions, if you ever ran the function as a standalone command (not inifor assignment),return 1would crash the script. Our solution maintains correctifbehavior while avoiding unexpected crashes in valid usage patterns.- Default value handling was unclear: The original code matched empty input but didn't have an explicit default variable, making it hard to adjust later.
内容的提问来源于stack exchange,提问作者winklerrr
相关产品推荐
相关产品推荐

