キーコードが右矢印キーでない場合でも、これが常にtrueとして検出されるのはなぜですか?
stty_state=`stty -g`
stty raw; stty -echo
keycode=`dd bs=1 count=1 2>/dev/null`
stty "$stty_state"
echo $keycode
if [ "$keycode"=39 ]; then
echo "Right Arrow Key Pressed!"
fi
キーコードが右矢印キーでない場合でも、これが常にtrueとして検出されるのはなぜですか?
stty_state=`stty -g`
stty raw; stty -echo
keycode=`dd bs=1 count=1 2>/dev/null`
stty "$stty_state"
echo $keycode
if [ "$keycode"=39 ]; then
echo "Right Arrow Key Pressed!"
fi
回答:
(おそらく)最初に2バイト以上を読み取ります。$keycode
矢印キーを押すと、スクリプト内でESCになります。
矢印キーは次のとおりです。
\x1b + some value
条件式にスペースがないため、常にtrueと評価されます。
編集:そのステートメントの更新。
あなたはif
の終了ステータスで動作する[
コマンド。[
コマンドは同等ですtest
。コマンドであるということはとても重要なことです。コマンドとしては、引数の間にスペースが必要です。この[
コマンドは]
、最後の引数として必要になるという点でさらに特別です。
[ EXPRESSION ]
コマンドは、EXPRESSIONによって決定された状況で終了します。1または0、trueまたはfalse。
括弧を書くのはエキゾチックな方法ではありません。つまり、Cの例のように、構文の一部ではありませんif
。
if (x == 39)
沿って:
if [ "$keycode"=39 ]; then
あなたが発行する:
[ "$keycode"=39 ]
に拡大する
[ \x1b=39 ]
ここ\x1b=39
は1つの引数として読み取られます。ときtest
や[
与えられた1つのそれが偽で終了引数場合にのみ、式がnullである-になるだろうことはありませんされています。$keycode
空であったとしても、結果は=39
(null /空ではない)になります。
それを見る別の方法はあなたが言うことです:
if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.
詳細は、これらの質問と回答を読む-だけでなく、上の議論[
対[[
:
その点で、バックティックを調査することもできます `` vs $( )
矢印キーを使用したマルチバイトエスケープシーケンス:
冒頭で述べたように、あなたは(おそらく)最初に2バイト以上を読み取ります。$keycode
矢印キーを押すと、スクリプト内でESCになります。
矢印やその他の特殊キーを使用すると、エスケープシーケンスがシステムに送信されます。ESCのバイト信号があること、「ここに異なって解釈されなければならないいくつかのバイトが来ます」。ASCIIになり、矢印キー用として[
ASCIIが続くA
、B
、C
またはD
。
つまり、矢印キーを処理する場合は、3バイトを解析する必要があります。
あなたはこれの方向に何かを試して確認することができます:
{ stty_state=$(stty -g)
stty raw isig -echo
keycode=$(dd bs=8 conv=sync count=1)
stty "$stty_state"
} </dev/tty 2>/dev/null
printf %s "$keycode" | xxd
産出:
HEX ASCII
1b 5b 41 .[A # Up arrow
1b 5b 42 .[B # Down arrow
1b 5b 43 .[C # Right arrow
1b 5b 44 .[D # Left arrow
| | |
| | +------ ASCII A, B, C and D
| +--------- ASCII [
+------------ ASCII ESC
これがどれほど移植可能かはわかりませんが、以前はこのようなコードをいじって、矢印キーをキャッチしていました。押しq
て終了します:
while read -rsn1 ui; do
case "$ui" in
$'\x1b') # Handle ESC sequence.
# Flush read. We account for sequences for Fx keys as
# well. 6 should suffice far more then enough.
read -rsn1 -t 0.1 tmp
if [[ "$tmp" == "[" ]]; then
read -rsn1 -t 0.1 tmp
case "$tmp" in
"A") printf "Up\n";;
"B") printf "Down\n";;
"C") printf "Right\n";;
"D") printf "Left\n";;
esac
fi
# Flush "stdin" with 0.1 sec timeout.
read -rsn5 -t 0.1
;;
# Other one byte (char) cases. Here only quit.
q) break;;
esac
done
(マイナーな注意点としてはあなたにも()に小数点以下39に対してテストつもり- 。10進数と16進数の間の重複が整理のように見えるエスケープシーケンスの最初のバイトは、ASCII値ESCで、小数点以下 27と16進0x1b
ながら、小数点以下 39は16進数です0x27
。 )
=
テスト内の記号を囲むスペースがないため、空ではない文字列として単に解析されるため、trueです。矢印キーが複数バイトであるという事実は別の問題です。
[
が組み込みのコマンドであると、人々はなぜスペースがはるかに迅速に重要であるのかを理解します。(括弧の代わりに括弧を使用するのは単にbashの奇妙な方法ではありません。)今すぐ実行する必要があります。一度更新してください。