首页 文章

Bash脚本用户输入提示

提问于
浏览
4

我遇到了生成用户输入提示的已知方法的问题:

read -p "Input something: " variabile

如果尝试使用箭头键,这会导致问题,它会回显每个箭头键击的ANSI代码

read -e -p "Input something: " variable

这解决了箭头键的问题,但是当达到终端的宽度时,文本输入不会在换行符上继续,而是在同一行上,覆盖(可视)现有输入

echo -n "Input something: "; read -e variable

这显然修复了以前描述的两个问题...直到我发现键入内容然后按下退格键覆盖提示,并且当输入更长时,从输入的第二个换行符再次显示视觉覆盖 .

那么有没有上述问题产生提示的好方法呢?

UPDATE

重新检查后,我现在知道是什么导致输入覆盖 read -e -p 我正在使用这些变量突出显示读取提示的文本:

highlight=$(echo -e "\e[1;97m")
clear=$(echo -e "\e[0m")
read -e -p "Input$highlight something$clear: " variable

这是我可以在 read 提示中进行突出显示工作的唯一方法(将转义序列分配给变量不起作用,我需要像我一样回应它们)但它们似乎也会导致输入覆盖问题 .

2 回答

  • 1

    正如dimo414提到的那样,readline认为提示比它更长 . 在计算长度时,它计算终端转义序列中的每个字符 . 您可以看到它认为转义序列的时间长度如下

    echo ${#highlight}
    

    在bash PS1提示符中,用 "\[""\]" 围绕这样的转义序列指示readline忽略计算当前行长度之间的所有内容,但这些不是bash read 内置的正确转义 .

    read 的转义是 $'\001'$'\002' ,如BashFAQ中所述,但根据我的经验,您还需要 read 上的 -e 选项 . 蛮力的方式做你想要的将是:

    read -e -p "Input "$'\001'"${highlight}"$'\002'something$'\001'"${clear}"$'\002'": "
    

    为了终端独立性,您应该使用tput而不是硬编码的转义序列 . 阅读 man 5 termcap .

    有关优雅的bash函数,请参阅my dotfiles以便为您执行上面的开始/结束引用 .

  • 1

    shell会跟踪它认为提示的时间长度,以便知道用户's input starts and stops. Unfortunately when you print color escape codes in a prompt you throw of Bash'的计数位置,因为它希望转义字符占用终端中的空间 .

    为了避免这种情况,您只需要在[ and ]中包装所有颜色序列,它会告诉您的shell所包含的字符是非打印的,不应计算在内 .

    例如,您的 highlight 变量应为:

    highlight=$(echo -e "\[\e[1;97m\]")
    

    就个人而言,我使用Prompt.gem项目中的color and pcolor函数来处理正确的转义,并使命令更容易阅读:

    read -e -p "Input $(pcolor DEFAULT BOLD)something$(pcolor): " variable
    

相关问题