Wie kann ich das Trennzeichen ausdrucken und dem Benutzer das Bearbeiten der Zeile beim Lesen der Standardeingabe ermöglichen?

Wie kann ich das Trennzeichen ausdrucken und dem Benutzer das Bearbeiten der Zeile beim Lesen der Standardeingabe ermöglichen?

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.3oder 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_semicolonin:

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.

verwandte Informationen