我正在寻找一种简单的解决方案,该解决方案将读取具有以下功能的用户输入:
我在Linux Read - Timeout after x seconds *idle*上找到了一个类似请求(每个键入的字符后超时)的解决方案。尽管如此,这并不是我一直在寻找的功能,所以我开发了一种两行式的解决方案,如下所示:
read -N 1 -t 10 -p "What is your name? > " a
[ "$a" != "" ] && read b && echo "Your name is $a$b" || echo "(timeout)"
如果用户在输入第一个字符之前等待10秒钟,则输出将为:
What is your name? > (timeout)
如果用户在10秒内键入第一个字符,则他将没有时间来完成此任务。输出将如下所示:
What is your name? > Oliver
Your name is Oliver
但是,下面有 caveat :第一个字符一旦输入就不可编辑,而其他所有字符都可以编辑(退格和重新键入)。
您是否有解决警告的想法,或者您对请求的行为有其他简单的解决方案?
答案 0 :(得分:1)
启用readline
并添加$a
作为第二次读取的默认值。
# 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
的超时。理想的解决方案是使用read
以外的其他命令 other ,但是您必须自己编写(可能是C中的可加载内置程序)。
答案 1 :(得分:1)
此解决方案可以。
read -n1 -t 10 -p "Enter Name : " name && echo -en "\r" &&
read -e -i "$name" -p "Enter Name : " name || echo "(timeout)"
注意:第二个read
使用从第一个(-i
选项)捕获的文本来提供可编辑的缓冲区。回车和相同的提示使用户印象中,他正在输入相同的值。
答案 2 :(得分:0)
测试条件: GNU bash,版本4.4.19(1)-发行 Ubuntu 18.04.2 LTS
我创建了一个函数来解决您对第一个字母不可编辑的警告,如下所示。我仅在本地linux服务器上进行了此测试,并且我不做任何假设,也可以在其他版本或BASH的较新/较旧版本中使用(对此也无法阅读,但我无法确定我运行的是哪个版本)>
.container-map {
width: 400px; /*set as much as you like */
}
.map-background , .map-search-results {
display: block;
height: 50%;
}
.map-background {
padding: 15px; /* set as much as you want - to affect the height/position of .map-filter */
}
.map-filter {
width: 200px;
height: 100%; /* top/bottom padding of [.map-background] will create the height differential here */
}
您可以调用类似于以下内容的函数:
__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
}
以上提到过的注意事项
因此,您有一个我已解决的警告,也许您(或我们的朋友)可以解决此问题。输入的任何未包含在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
REGEX变量中的字符都将被视为BACKSPACE。这意味着您的用户可以打$rg
,F7
,=
,或者实际上是\
中指定的字符以外的任何其他字符,并且它将被视为退格< / strong>
答案 3 :(得分:0)
在第一个读取命令上添加-s
选项,在第二个读取命令上添加-ei
选项:
read -s -N 1 -t 10 -p "What is your name? > " a
[ "$a" != "" ] && read -ei "$a" b && echo "Your name is $b" || echo "(timeout)"
或者更好地处理空输入:
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的答案(感谢-ei
选项!)和@ paul-hodges的评论,这使我撰写了一篇介绍-s
读取选项的文章,能够创建与我的原始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)"
您中的某些人可能会喜欢具有相同功能的更精致的版本:
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
说明:
-s
选项将确保在键入时未打印出FIRST_CHARACTER。-N 1
或-n1
选项将确保仅将第一个字符读入FIRST_CHARACTER变量-ei
选项将$FIRST_CHARACTER
读入FULL_NAME。我试了一下,这些选项的组合似乎可以解决问题。
但是,仍然有一个小警告:如果用户仅键入<enter>
:第二条读取命令将等待输入,直到用户再次按下<enter>
为止。可以像下面这样固定它:
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
采用两线式样式,这将为我们提供三线式,如下所示:
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\""
两个版本的代码(如果版本嵌套,则为三行代码)的行为如下:
What is your name? (timeout)
Oliver<enter>
,则输出为What is your name? Oliver
Your name is "Oliver"
What is your name? Oliver
输入名称“ Oliver”后。然后,在按退格键6次或更多次之后:
What is your name?
在输入Michael<enter>
之后:
What is your name? Michael
Your name is "Michael"
希望有帮助。