
端末から入力行を徐々に読み、ユーザーにINS、DEL、右、左、終了、バックスペース機能を許可したいと思います。
文字列が変更されるたびにそれを処理して、テキストファイルに対して増分正規表現検索を実行したいと思います。
これらの編集キーと他のキーは複数の入力文字を生成するため、
入力を解釈するのは非常に困難です。たとえば、C-Leftは6文字を生成します。
文字ごとに編集可能な入力を簡単に取得する方法はありますか?
残りの処理はbashで行われるので、bashでこれを行う方法を知りたいです。他の提案も歓迎します。
それで始めましたが、潜在的な制御コードが多すぎて少し余裕がありませんでした。
#!/bin/bash
IFS=$'\n'
while true ;do
read -n 1 c
((${#c}==0)) && break # Exit the loop. Input length is 0
# ie. The user has pressed Enter
echo "xx=$(echo -n "$c"|xxd -p)="
# 1b 5b 32 7e "INS"
# 1b 5b 33 7e "DEL"
# 1b 5b 43 "RIGHT"
# 1b 5b 44 "LEFT"
# 1b 5b 46 "END"
# 1b 5b 48 "HOME"
# 7f "BACKSPACE"
done
答え1
一度に1文字ずつ読み込む場合は、read -n
キーシーケンスパーサを実装する必要があります。以下を使用して、ほとんどの端末で動作する遅くて汚れたソリューションを構築できます。エスケープ文字で始まり、任意の数の文字で続くファンクションキーエスケープシーケンスを考慮して、この文字セットにない0-9;[]O
最後の文字が続きます。
入力を読み取るより良い方法は、適切な入力ライブラリを使用することです。 Bashはこれを独自の目的に使用します(読書船)。組み込みを使用してbind
独自のキーバインディングを宣言すると、bind -x
キーを押したときにシェルコマンドを実行するように特別に設計された制限付きインターフェイスを取得できます。制限されたインターフェイスのために、必要なものを実装することは可能かもしれませんが、難しいです。
Zshには独自の入力ライブラリがあります。ズラー。インターフェイスはbashよりはるかに豊富です。 zleを使用すると、任意のキーマップを定義でき、シェルコードからzleの内部機能にアクセスできます。zle
カスタムコマンド(ウィジェットと呼ばれる)にシェル機能を割り当て、bindkey
独自のキーマップを作成および入力し、最後にvared
選択したキーマップを使用して入力行を読み取るために使用されます。
答え2
read
文字がある場合は、最初の端末の後に端末をネイティブモードに設定してから、2番目の端末を使用して残りのバイトesc
(read
存在する場合)を読み取って解析できます(参照)。BASHはキャラクタートラウマから抜け出した。また見てください矢印.txt)。
#!/bin/bash
# tested on Mac OS X 10.6.8
IFS=$'\n'
old_tty_settings="$(stty -g)"
exec 0</dev/tty
tput smir # enable insert mode
while IFS="" read -r -s -n1 key; do # first read (reads only a single byte)
#od -c <<<"$key"
#continue
((${#key}==0)) && break
case "$key" in
$'\001') printf '\r' # ctrl-a
continue;;
$'\177') tput rmir
printf "\010\040\010\033[P" # backspace
tput smir
continue;;
$'\025') printf "\033[1K" # tput el1 does not work on Mac OS X 10.6.8
continue;; # ctrl-u (clear to start of line)
$'\v') tput el
continue;; # ctrl-k (clear to end of line)
esac
# if the first char is esc (i.e. \e or \033 respectively)
if [[ "$key" == $'\033' ]]; then
stty cbreak -echo min 0 time 0 # set raw terminal
IFS="" read -r bytes # second read (reads remaining bytes)
if [[ ${#bytes} -gt 0 ]]; then
stty "$old_tty_settings"
case "${key}${bytes}" in
$'\033[3~') tput dch1 # delete one char
continue;;
esac
printf "${key}${bytes}"
else
stty "$old_tty_settings"
fi
else
#stty "$old_tty_settings"
printf '%s' "$key"
fi
done
echo
exit 0
答え3
コマンドラインツールを見るセレクタ。
# usage examples
selector -v -x @ <(find . -maxdepth 2 -type d | awk '{print $0"@cd "$0}')
selector -v -x @ <(grep -E -o 'http[^ ]+' fileWithURLS)
答え4
スクリプトを使用せずにbash組み込み機能のみを使用してください。
read -e INPUT # single line
INPUT=$(</dev/stdin) # multiple lines
(源泉)
または、ledit
パッケージをインストールしたら、次のものを使用できます。
INPUT=$(ledit)