シェルスクリプトは、EnterキーとTabキーを介して「読み取り」を許可します。

シェルスクリプトは、EnterキーとTabキーを介して「読み取り」を許可します。

シェルスクリプトで次のような場合:

read my_variable

Enter入力を保存するキーです。

機能を削除せずにTab同じことを行う方法はありますか?EnterEnter

答え1

read -e少し過剰かもしれませんが、ユーティリティでReadlineツールを有効にすることで取得できますread。その時点で、目的の結果を得るためにキーを押すだけです。

しかし注意してください。 Readlineは、単純化のために完成、記録などの他の多くの機能も提供しますread my_variable。これらの機能が必要ない場合は、明示的にキーバインディングを消去し、不要な機能を無効にする必要がありますread -e

コマンドラインの概念証明の例:

(bind 'TAB: accept-line'; IFS= read -re var && echo "$var" || echo ko)

bind警告は表示されますが、スクリプトでもこれを行うことができます(リダイレクトを使用して警告を沈黙させることができます2>/dev/null)。

スクリプトのコマンドの代替案は、bind影響を及ぼすスクリプトを呼び出す前にカスタム inputrc ファイルを提供することです。実際の文書は必要ありません。ここの文書で十分です。

上記の例はスクリプトによって実装されています。

#!/bin/bash

export INPUTRC=/dev/fd/3

script2.sh 3<<EOF
TAB: accept-line
set history-size 0
EOF
# this example 'inputrc'-like file also disables history support

上記のスクリプトはカスタムinputrcファイルをファイル記述子3のHere Documentとして準備し、実行中のシェルは環境変数の指示に従ってファイルを読み取りますscript2.shINPUTRC

それからscript2.sh

#!/bin/bash

echo start
bind -q accept-line 2>/dev/null  # shows which keys are configured to accept input
IFS= read -re var && echo "$var" || echo ko
echo end

入力を待つ前に、readスクリプトは次のように印刷します。

accept-line can be invoked via "\C-i", "\C-j", "\C-m".

ディスプレイTabCtrl-I例:上記のもの)\C-iは、行のプラス(キャリッジリターンなど)または改行()を許可します。ReturnCtrl-MCtrl-J

もう少し「実際」の例を次に示します。

#!/bin/bash

bind 'TAB: accept-line' &>/dev/null

echo "enter your name:"
IFS= read -re var 

echo "your name is: $var"

この道に降りたらぜひご覧くださいReadlineユーザーガイド、あなたの項目の1つ以上が減少しましたman bashset convert-meta off非ASCII文字のより良いサポートのために、これらの設定について特に言及する価値があります。

答え2

通常、これを行うには、//特殊文字(「代替行末」)をtermios(3)Tabに設定することです。これをサポートするシステムでは/も使用できます。stty(1) VEOLeolVEOL2eol2

残念ながら、read組み込みシェルは常に改行文字(またはbashifで-d使用されている他の区切り文字、複数の区切り文字はサポートされていません)を読み取ろうとします。

この問題を解決する1つの方法は、var=$(dd count=1 bs=big)代わりにコマンド置換を使用することですread。以下はこれの例です。

while :; do

        t=$(stty -g)
        stty eol ^I
        trap : INT
        var=$(dd bs=10k count=1 2>/dev/null; echo x)
        stty "$t"
        trap - INT
        var=${var%x}
        [ "$var" ] || break
        var=${var%[$'\n\t']}

        printf '{%s}\n' "$var"

done

端末設定を保存して復元しますt=(stty -g)stty "$t"

Control-Cがシェル/ループ(およびそれに伴うすべての合併症およびシェル関連の動作)を終了するのを防ぎ、コマンド置換のみを終了させますtrap : INTtrap - INTdd

以下は、コマンドの置き換えから末尾の改行が削除されるのを防ぐためのトリック$(...; echo x)です。これは、単に空の変数を押すか、ループを終了するユーザーを区別できるようにするために必要です。${var%x}EnterControl-CControl-D

最後に、${var%[$'\n\t']}末尾の改行またはタブが変数から削除されます。 orなどの文字列をサポートしていないシェルでは、$'...'これを次のように置き換えることができます。dashyash

nltab='<literal tab here>
'
...
var=${var%[$nltab]}

関連情報