Bash脚本用户输入提示

Bash script user input prompt

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

read -p "Input something: " variabile

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

read -e -p "Input something: " variable

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

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

这显然解决了之前描述的两个问题...直到我发现输入内容然后按退格键会覆盖提示,而且当输入较长时,从输入的第二个换行符开始,视觉覆盖再次出现。

那么有没有好的提示方式可以避免上述问题呢?

更新

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

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

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

shell 跟踪它认为 提示的时间,以便了解用户输入的开始和停止位置。不幸的是,当您在提示中打印颜色转义码时,您会抛出 Bash 的计数,因为它希望转义字符在终端中占据 space。

为避免这种情况,您只需要将所有颜色序列包裹在 \[ and \] 中,这告诉您 shell 封闭的字符是非打印字符,不应计算在内。

例如,您的 highlight 变量应该是:

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

就我个人而言,我使用 color and pcolor functions from my Prompt.gem 项目,它处理正确的转义并使您的命令更容易阅读:

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

正如 dimo414 提到的,readline 认为提示比实际的要长。它在计算长度时计算终端转义序列中的每个字符。可以看到它认为转义序列有多长如下

echo ${#highlight}

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

read 的转义符是 $'[=16=]1'$'[=17=]2',如 BashFAQ 中所述,但根据我的经验,您需要 -e 选项read,还有。做你想做的事的蛮力方式是:

read -e -p "Input "$'[=11=]1'"${highlight}"$'[=11=]2'something$'[=11=]1'"${clear}"$'[=11=]2'": "

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

请参阅 my dotfiles 以获取优雅的 bash 函数来为您执行上面的 begin/end 引用。