標準入力の読み取り中に区切り文字を印刷し、ユーザーが行を編集できるようにするにはどうすればよいでしょうか?

標準入力の読み取り中に区切り文字を印刷し、ユーザーが行を編集できるようにするにはどうすればよいでしょうか?

; 標準入力から読み取り、文字を区切り文字として使用して入力行を終了し、ユーザーが行を編集できるようにする簡単なスクリプトを作成しようとしています 。

これが私のテストスクリプトです:

#!/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それ以上の場合は、次のようなハックで同様のことを行うことができます。

# 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//;}"で表示するにはウィジェットに挿入する必要があります。zlereadline

関連情報