Ich versuche, ein einfaches Skript zu schreiben, das von der Standardeingabe liest und dabei ;
Zeichen als Trennzeichen zum Beenden der Eingabezeile verwendet und dem Benutzer das Bearbeiten der Zeile ermöglicht.
Hier ist mein Testskript:
#!/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
Dies funktioniert, druckt aber das Trennzeichen „;“ nicht aus:
# bash test.sh
><> startApp
startApp command
><> stopApp
stopApp command
><> end
Wenn ich die Option -e entferne, wird es zwar ausgedruckt, ;
aber der Benutzer kann seinen Fehler nicht mit dem Rücktastezeichen korrigieren, und die wiedergegebenen Zeichenfolgen stehen direkt nach dem Trennzeichen:
# bash test.sh
><> startApp;startApp command
><> stopApp;stopApp command
><> end;
Wie kann ich das Trennzeichen ausdrucken und dem Benutzer das Bearbeiten der Zeile beim Lesen der Standardeingabe ermöglichen?
Dies ist das erwartete Verhalten:
# bash test.sh
><> startApp;
startApp command
><> stopApp;
stopApp command
><> end;
Danke
Antwort1
Ich würde es verwenden zsh
, wo der Zeileneditor über viel mehr Funktionen verfügt und viel besser anpassbar ist:
#! /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
Mit bash-4.3
oder höher können Sie etwas Ähnliches mit einem Hack wie diesem erreichen:
# 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
Beachten Sie, dass in dieser Version ;
immer am Ende des Eingabepuffers eingefügt wird, nicht an der aktuellen Cursorposition. Ändern Sie add_semicolon
in:
add_semicolon() {
READLINE_LINE="${READLINE_LINE:0:READLINE_POINT++};"
}
Wenn Sie möchten, dass es an der Cursorposition eingefügt und alles rechts davon verworfen wird. Oder:
add_semicolon() {
READLINE_LINE="${READLINE_LINE:0:READLINE_POINT};${READLINE_LINE:READLINE_POINT}"
READLINE_POINT=${#READLINE_LINE}
}
wenn Sie es am Cursor einfügen möchten, aber wie im Ansatz das, was rechts steht, beibehalten möchten zsh
.
;
Wenn Sie das in nicht möchten $srcCommand
, können Sie es nachträglich srcCommand="${srcComman//;}"
beispielsweise immer noch entfernen, aber Sie müssen es in das Widget einfügen, damit es von zle
/ angezeigt wird readline
.