bashscript检测右箭头键被按下


Answers:


16

您(可能)会先读取两个以上的字节。$keycode当您按下箭头键时,脚本中的ESC将为ESC。

箭头键可以是:

\x1b + some value

由于条件表达式中缺少空格,因此始终将其评估为true。

编辑:该声明的更新。

if[命令的退出状态进行操作。该[命令等效于test。它是命令这一事实是非常重要的事实。作为命令,它要求参数之间有空格。该[命令的特殊之处在于它需要]作为最后一个参数。

[ EXPRESSION ]

该命令以EXPRESSION确定的状态退出。1或0,

不是写括号的奇特方法。换句话说,它不是if语法的一部分,例如在C中:

if (x == 39)

通过:

if [ "$keycode"=39 ]; then

您发出:

[ "$keycode"=39 ]

扩展到

[ \x1b=39 ]

这里\x1b=39被视为一个论点。当test[给出一个说法是假退出只有当表达式为空-这是永远不会是。即使$keycode为空,也将导致=39(不为null /空)。

另一种查看方式是您说:

if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.

阅读这些问题和答案以获取更多详细信息-以及关于[vs的讨论[[

在这方面,您还可以研究壁虱``vs $( )


带箭头键的多字节转义序列:

如顶部所述:您(可能)从两个以上的字节中首先读取。$keycode当您按下箭头键时,脚本中的ESC将为ESC。

箭头键和其他特殊键会导致转义序列发送到系统。该ESC字节的信号是“这里来一些字节应该以不同的解释”。至于箭头键这将是ASCII [其次是ASCII ABCD

换句话说,在处理箭头键时必须解析三个字节。

您可以尝试按以下方向进行检查:

{   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进行测试–看起来像是十进制和十六进制之间的混合。转义序列的第一个字节是ASCII值ESC,它是十进制 27和十六进制0x1b,而十进制 39是十六进制0x27。 )


2
问题中的第一个问题是=测试中的符号周围没有空格,因此将其简单地解析为非空字符串,因此为真。箭头键是多个字节的事实是一个单独的问题。
wurtel

2
嗯,那句话并没有太多上下文,因为我认为那是我已经知道的多字节序列解释的一部分,所以我读了一下。
wurtel

2
@wurtel:是的。我想含糊其辞。发现一旦有人解释[是内置命令,人们就会更快地理解为什么空间很重要。(使用括号而不是括号并不是bash的一种怪异方式。)必须立即用完。更新一次。
user367890
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.