bash read timeout only for the first character entered by the user
我已经搜索了一个简单的解决方案,它将读取具有以下功能的用户输入:
- 10秒后超时,如果完全没有用户输入
- 如果在前10秒内键入了第一个字符,则用户有无限的时间来完成其回答。
我在Linux上找到了一个类似的请求(每键入一个字符后超时)的解决方案read-timeout after x seconds*idle*。不过,这并不是我想要的功能,因此我开发了一个两行解决方案,如下所示:
1 2 | read -N 1 -t 10 -p"What is your name? >" a ["$a" !="" ] && read b && echo"Your name is $a$b" || echo"(timeout)" |
如果用户在输入第一个字符前等待10秒,则输出将为:
1 | What is your name? > (timeout) |
如果用户在10秒内键入第一个字符,他将有无限的时间来完成此任务。输出如下:
1 2 | What is your name? > Oliver Your name is Oliver |
但是,需要注意的是:第一个字符一旦输入就不可编辑,而所有其他字符都可以编辑(退格键和重新输入)。
您对警告的解决有什么想法吗,或者您对请求的行为有其他简单的解决方案吗?
这个解决方案可以。
1 2 3 | read -n1 -t 10 -p"Enter Name :" name && echo -en" " && read -e -i"$name" -p"Enter Name :" name || echo"(timeout)" |
注:第二个
启用
1 2 3 4 5 6 7 8 9 10 | # read one letter, but don't show it read -s -N 1 -t 10 -p"What is your name? >" a if [ -n"$a" ]; then # Now supply the first letter and let the user type # the rest at their leisure. read -ei"$a" b && echo"Your name is $b" else echo"(timeout)" fi |
在第一个字母被回答后,它仍然显示第二个提示,但我认为没有更好的方法来处理这个问题;没有办法"取消"
简短回答:
在第一个read命令中添加一个
1 2 | read -s -N 1 -t 10 -p"What is your name? >" a ["$a" !="" ] && read -ei"$a" b && echo"Your name is $b" || echo"(timeout)" |
或者更好地处理空输入:
1 2 3 | read -s -N 1 -t 10 -p"What is your name? >" a || echo"(timeout)" \ && [ -n"$a" ] && read -ei"$a" b || echo \ && echo"Your name is "$b"" |
详细回答:
在@chepner回答的帮助下(感谢
1 2 | read -N 1 -t 10 -s -p"What is your name? >" a ["$a" !="" ] && read -ei"$a" b && echo"Your name is $b" || echo"(timeout)" |
你们中的一些人可能会喜欢同样功能的更详细的版本:
1 2 3 4 5 6 | if read -N 1 -t 10 -s -p"What is your name?" FIRST_CHARACTER; then read -ei"$FIRST_CHARACTER" FULL_NAME echo"Your name is $FULL_NAME" else echo"(timeout)" fi |
说明:
- 第一个read命令中的
-s 选项将确保在键入时不打印第一个字符。 -N 1 或-n1 选项将确保只有第一个字符被读取到第一个字符变量中。- 在用户继续将字符2写入n之前,
-ei 选项将把$FIRST_CHARACTER 读入全名。 - 用户可以重新考虑他的答案,他可以删除整个输入,包括退格键的第一个字符。
我已经测试过了,这些选项的组合似乎起到了作用。
用空输入解决警告但是,还有一个小警告:如果用户只键入
1 2 3 4 5 6 7 8 9 10 | if read -N 1 -t 10 -s -p"What is your name?" FIRST_CHARACTER; then if [ -n"$FIRST_CHARACTER" ]; then read -ei"$FIRST_CHARACTER" FULL_NAME else echo fi echo"Your name is "$FULL_NAME"" else echo"(timeout)" fi |
在双衬板的样式中,这将为我们提供一个三衬板,如下所示:
1 2 3 | read -N 1 -t 10 -s -p"What is your name? >" a || echo"(timeout)" \ && [ -n"$a" ] && read -ei"$a" b || echo \ && echo"Your name is "$b"" |
试验
两个版本的代码(嵌套的if版本和三行程序)的行为如下:
- 如果用户在10秒内不做任何事情,输出将产生
1 | What is your name? (timeout) |
- 如果用户写入
Oliver ,则输出将为
1 2 | What is your name? Oliver Your name is"Oliver" |
- 如果用户开始写"奥利弗",然后认为他想被称为"迈克尔",他可以用退格键完全删除"奥利弗",并相应地替换它。输出将是:
1 | What is your name? Oliver |
在输入"奥利弗"的名字后。然后,在按退格键6次或更多次后:
1 | What is your name? |
进入
1 2 | What is your name? Michael Your name is"Michael" |
希望有帮助。
试验条件:GNU bash,版本4.4.19(1)-发布Ubuntu 18.04.2升
我创建了一个函数来解决第一个字母不可编辑的警告,如下所示。我只在我的本地Linux服务器上测试过这个版本,并且我没有假设这个版本在其他地方或者在新的/旧的bash版本上可以工作(或者为此进行读取,但是我无法知道我运行的是哪个版本)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | __readInput(){ str="What is your name? >" tput sc # Save current cursor position printf"$str" read -n 1 -t 10 a # Wait 10 seconds for first letter [[ $? -eq 0 ]] || return 1 # Return ErrorCode"1" if timed_out while :; do # Infinite Loop tput rc # Return cursor to saved position printf"$str$a" # Print string (including what is saved of the user input) read -n 1 b # Wait for next character if [[ $? -eq 0 ]]; then # We had proper user input if [[ ${#b} -eq 0 ]]; then # User hit [ENTER] n=$a$b break # End our loop fi rg="[A-Za-z-]" # REGEX for checking user input... CAVEAT, see below if ! [[ $b =~ $rg ]] ;then # We have an unrecognisied character return, assume backspace [[ ${#a} -gt 0 ]]&&a=${a:0:(-1)} # Strip last character from string tput rc # Return cursor to saved position printf"$str$a " # This removes the ^? that READ echoes on backspace continue # Continue our loop fi a=$a$b # Append character to user input fi done } |
您可以调用类似以下的函数:
1 2 3 4 5 6 7 | declare n="" __readInput if [[ $? -eq 0 ]] || [[ ${#n} -eq 0 ]] ;then echo"Your name is $n" else echo"I'm sorry, I didn't quite catch your name!" fi |
上述警告已解释所以,你有一个警告,我修复了,也许你(或我们的朋友)可以修复这个。输入的任何未包含在