如何列印出分隔符號並允許使用者在讀取標準輸入時編輯行?

如何列印出分隔符號並允許使用者在讀取標準輸入時編輯行?

我正在嘗試編寫一個從標準輸入讀取的簡單腳本,使用 ; 字元作為分隔符號來終止輸入行,並允許使用者編輯行。

這是我的測試腳本:

#!/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或以上,您可以透過 hac​​k 執行類似的操作,例如:

# 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

相關內容