やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

シェルのreadコマンドで方向キーが効かない(←が^[[Dになる)

 ずっと前からダメでした。向き合ってください。

再現手順

  1. ターミナル(LxTerminal)を起動する
  2. readコマンドを実行する
  3. aaaなどと入力する
  4. キーを入力する
  5. ^[[Dと表示されてしまいカーソル移動できない……
$ read
aaa^[[D

 ずっと前から気になっていたので調べたところread -eで解決することが分かった。

調査

参考

端末のキーバインド

$ stty -a
speed 38400 baud; rows 31; columns 157; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc

 なにこれきもい。

シェルのキーバインド

bind -p | egrep -v '^#|self-insert|do-lowercase-version|digit-argument'
定義名 意味
backward-char 1文字戻る
forward-char 1文字進む
$ bind -p | grep 'backward-char'
"\C-b": backward-char
"\eOD": backward-char
"\e[D": backward-char

 Ctrl+Bで戻れそうだが入力してみたら^Bと出力された……。

$ read
aaa^B

解決

read -e

man bashに書いてあった

man bash
READLINE ライブラリ
       readline は対話シェルを使うときに入力の読み込みを処理するライブラリです。 ただし、シェルの起動時に --noediting  オプションが指定された場合には使わ
       れません。 行編集は組み込みコマンド read に -e オプションを 指定したときにも使われます。 デフォルトでは、行編集に使うコマンドは emacs のコマンドに
       似ています。 vi 形式の行編集インタフェースも使えます。 行編集は、組み込みコマンド set (後述の シェルの組み込みコマンド を参照) に -o emacs  や  -o
       vi  オプションを指定することで、いつでも有効にできます。 シェルを起動した後に行編集機能を無効にするには、組み込みコマンド set に対して +o emacs オ
       プションまたは +o vi オプションを設定してください。

 readlineコマンドは無かった。read -eで使えた。

readのヘルプ

$ read --help
...
      -e    use Readline to obtain the line in an interactive shell
...
$ trans {en:ja} "use Readline to obtain the line in an interactive shell"
対話シェルで行を取得するにはReadlineを使用してください。

Readlineとは?

 まさかのWeblio辞書。

readline 関数群は、GNU Readline ライブラリへの インターフェースを実装したものです。これらの関数は、コマンドラインの 編集機能を提供します。

注意: この拡張モジュールは Windows 環境では利用できません。

readline 関数を使用するには、libreadline をインストールすることが 必要です。

 私の環境ではデフォルトで入っていたのか?

ショートカットキー

key 意味
/C-b カーソル移動(左へ1文字)
/C-f カーソル移動(右へ1文字)
Home/C-a カーソル移動(行頭)
End/C-e カーソル移動(行末)
key 意味
/C-p 履歴(前)
/C-p 履歴(次)
key 意味
BkSp/C-h 直前の1文字を削除
Del/C-d 直後の1文字を削除
C-u カーソル以前の字をすべて削除
C-k カーソル以降の字をすべて削除
C-y 直前に削除した文字列をペースト(貼り付け)
key 意味
<tab> 単語補完
  • C-bCtrl+Bのこと
  • 日本語キーボードにメタキーがない。M-x系ショートカットキーが使えない……
  • 選択モードがない……コピーできない

 以下参考。

viモード

set -o vi
read -e
キー モード
ESC ノーマルモード
a, i 追記, 挿入モード
h,j,k,l ノーマルモード時にカーソル移動

 選択モードがない。範囲選択コピーしたい。

所感

 積年の悩みが解決してスッキリ!

 関係ないけど気になるのを見つけたのでメモ。

対象環境

  • Raspbierry pi 3 Model B+
  • Raspbian stretch 9.0 2018-11-13
  • bash 4.4.12
$ uname -a
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux