キーコードが右矢印キーでない場合でも常に真を検出するのはなぜですか?
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
答え1
(おそらく)最初に2バイト以上を読みました。$keycode
矢印キーを押すと、スクリプトはESCになります。
矢印キーは次のとおりです。
\x1b + some value
条件式には空白がないため、常に真と評価されます。
編集:この声明を更新してください。
if
コマンドの終了状態に基づいて作業します[
。この[
コマンドはtest
実際には同じです。注文するこれは非常に重要な事実です。コマンドとして引数の間にスペースが必要です。このコマンドのより特別な点は、最後のパラメータとして[
必要であることです。]
[ EXPRESSION ]
コマンドはEXPRESSIONによって決定された状態で終了します。 1または0、本物または間違った。
これはいいえかっこを書く奇妙な方法。つまりいいえ構文の一部(if
例:C:)
if (x == 39)
通過:
if [ "$keycode"=39 ]; then
あなたは以下を発行します:
[ "$keycode"=39 ]
次に展開
[ \x1b=39 ]
ここでは、次のよう\x1b=39
に読みます一つ議論。いつtest
または[
与えられたか一つパラメータがfalseで終了します。〜しない限りEXPRESSIONは空です。これは決して真実ではありません。$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[
の後にASCIIA
またはです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
(小さめに、10進数と16進数が混在しているように見える10進数39についてもテストします。エスケープシーケンスの最初のバイトは次のとおりです。ASCII値ESC今すぐ少数27および16進数0x1b
、一方少数39は16進数です0x27
。 )