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

如何在Bash中逐字符过滤密码输入、抑制ESC序列并限制首字符

实现带过滤规则的逐字符密码输入(无read -e)

要实现符合要求的密码输入逻辑,需要在逐字符读取的基础上,加入首字符校验、特殊字符过滤、ESC序列识别和退格处理,以下是完整实现:

#!/bin/bash

# 定义允许的字符集合
allowedDefaultChars='[a-zA-Z0-9]'
allowedSpecialChars='[-_ \(\)/~?!§,.\#+]'
pw=""

while true; do
    # 逐字符读取,-r不转义,-s不回显,-n1只读一个字符
    read -rsn 1 input_char

    # 处理空输入(比如某些终端的特殊情况)
    [[ -z "$input_char" ]] && continue

    # 处理ESC序列(方向键、功能键等以ESC开头的非打印序列)
    if [[ "$input_char" == $'\e' ]]; then
        # 读取ESC后的后续字符,直接丢弃整个序列
        read -rsn 2 -t 0.1
        continue
    fi

    # 处理退格键(ASCII 127或^H)
    if [[ "$input_char" == $'\x7f' || "$input_char" == $'\x08' ]]; then
        # 密码不为空时才删除最后一个字符
        if [[ -n "$pw" ]]; then
            pw="${pw%?}"
            # 输出退格+空格+退格,实现视觉上的删除效果
            printf '\b \b'
        fi
        continue
    fi

    # 处理回车键(结束输入)
    if [[ "$input_char" == $'\n' || "$input_char" == $'\r' ]]; then
        # 确保密码非空才退出循环
        [[ -n "$pw" ]] && break
        continue
    fi

    # 首字符校验:只能是字母或数字
    if [[ -z "$pw" ]]; then
        if [[ "$input_char" =~ $allowedDefaultChars ]]; then
            pw+="$input_char"
            printf '*' # 输出星号作为输入反馈
        fi
    else
        # 后续字符允许字母数字+指定特殊字符
        if [[ "$input_char" =~ $allowedDefaultChars || "$input_char" =~ $allowedSpecialChars ]]; then
            pw+="$input_char"
            printf '*' # 输出星号作为输入反馈
        fi
    fi
done

# 换行,避免后续输出和密码提示符混在一起
echo
echo "输入的密码为:$pw"

关键逻辑说明

  • ESC序列过滤:当读取到ESC字符($'\e')时,立即读取后续2个字符(方向键等序列一般是ESC+2个字符)并丢弃,避免这些非打印字符污染密码。-t 0.1设置超时,防止终端无响应。
  • 退格处理:识别ASCII退格(\x7f)和Ctrl+H(\x08),删除密码的最后一个字符,同时输出\b \b实现终端上的字符删除视觉效果。
  • 首字符限制:密码为空时,只接受字母或数字;密码非空后,才允许指定的特殊字符。
  • 输入反馈:每输入一个合法字符,输出一个*,让用户知道输入已被接受,同时隐藏真实密码内容。
  • 结束输入:按下回车(\n或\r)且密码非空时,退出循环完成输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:03:20