我正在尝试编写一个从标准输入读取的简单脚本,使用 ;
字符作为分隔符来终止输入行,并允许用户编辑行。
这是我的测试脚本:
#!/bin/bash
while true; do
read -e -d ";" -t 180 -p "><> " srcCommand
if [ $? != 0 ]; then
echo "end;"
echo ""
exit 0
fi
case "$srcCommand" in
startApp)
echo "startApp command";;
stopApp)
echo "stopApp command";;
end)
echo ""
exit 0
;;
*)
echo "unknown command";;
esac
done
这有效,但不打印分隔符“;”字符:
# bash test.sh
><> startApp
startApp command
><> stopApp
stopApp command
><> end
如果我删除 -e 选项,它会打印出来, ;
但用户无法使用退格字符纠正他的错误,并且回显的字符串就在分隔符之后:
# bash test.sh
><> startApp;startApp command
><> stopApp;stopApp command
><> end;
如何打印出分隔符并允许用户在读取标准输入时编辑行?
这是预期的行为:
# bash test.sh
><> startApp;
startApp command
><> stopApp;
stopApp command
><> end;
谢谢
答案1
我会zsh
在行编辑器具有更多功能并且更可定制的地方使用:
#! /bin/zsh -
insert-and-accept() {
zle self-insert
# RBUFFER= # to discard everything on the right
zle accept-line
}
zle -N insert-and-accept
bindkey ";" insert-and-accept
bindkey "^M" self-insert
vared -p "><> " -c srcCommand
使用bash-4.3
或以上,您可以通过 hack 执行类似的操作,例如:
# bind ; to ^Z^C (^Z, ^C otherwide bypass the key binding when entered
# on the keyboard). Redirect stderr to /dev/null to discard the
# useless warning
bind '";":"\32\3"' 2> /dev/null
# new widget that inserts ";" at the end of the buffer.
# If we did bind '";":";\3"', readline would loop indefinitely
add_semicolon() {
READLINE_LINE+=";"
((READLINE_POINT++))
}
# which we bind to ^Z
bind -x '"\32":add_semicolon' 2> /dev/null
# read until the ^C
read -e -d $'\3' -t 180 -p '><> ' srcCommand
请注意,在该版本中,;
始终插入到输入缓冲区的末尾,而不是当前光标位置。将其更改add_semicolon
为:
add_semicolon() {
READLINE_LINE="${READLINE_LINE:0:READLINE_POINT++};"
}
如果您希望将其插入到光标处并丢弃右侧的所有内容。或者:
add_semicolon() {
READLINE_LINE="${READLINE_LINE:0:READLINE_POINT};${READLINE_LINE:READLINE_POINT}"
READLINE_POINT=${#READLINE_LINE}
}
如果您想将其插入到光标处但想保留右侧的内容,就像zsh
方法中一样。
如果您不想要;
in $srcCommand
,您可以随时将其删除,srcCommand="${srcComman//;}"
例如,但您需要将其插入小部件中才能通过zle
/显示readline
。