bashscript เพื่อตรวจจับปุ่มลูกศรขวาถูกกด


9

ทำไมสิ่งนี้ถึงตรวจพบว่าเป็นจริงเสมอแม้ว่ารหัสคีย์นั้นจะไม่ถูกต้องลูกศรขวา

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

คำตอบ:


16

คุณ (เป็นไปได้) อ่านก่อนจากสอง + ไบต์ $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หรือ[ได้รับหนึ่งอาร์กิวเมนต์มันจะออกด้วยเท็จเฉพาะในกรณีที่การแสดงออกเป็นโมฆะ - ซึ่งจะไม่เป็นไป แม้ว่าจะ$keycodeว่างเปล่าก็จะส่งผลให้=39(ซึ่งไม่เป็นโมฆะ / ว่างเปล่า)

อีกวิธีในการดูคือคุณพูดว่า:

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

อ่านคำถามและคำตอบสำหรับรายละเอียดเพิ่มเติมรวมถึงการอภิปรายเกี่ยว[กับ vs [[:

ในเรื่องนั้นคุณสามารถวิจัยย้อนกลับติ๊ก `` กับ $( )


ลำดับการหลบหลีกหลายไบต์พร้อมปุ่มลูกศร:

ดังที่กล่าวไว้ด้านบน: คุณ (น่าจะ) อ่านก่อนจากสองไบต์ $keycodeในสคริปต์ของคุณจะเป็น ESC เมื่อกดปุ่มลูกศร

ลูกศรและปุ่มพิเศษอื่น ๆ ส่งผลให้escape sequencesถูกส่งไปยังระบบ ESCไบต์สัญญาณว่า"นี่มาไบต์บางอย่างที่ควรจะตีความที่แตกต่างกัน" สำหรับปุ่มลูกศรที่จะเป็นแอสกี[ตาม ASCII A, B, หรือCD

กล่าวอีกนัยหนึ่งคุณต้องแยกสามไบต์เมื่อจัดการกับปุ่มลูกศร

คุณสามารถลองบางสิ่งในทิศทางนี้เพื่อตรวจสอบ:

{   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 -. ซึ่งมีลักษณะเหมือน Mixup ระหว่างทศนิยมและเลขฐานสิบหกไบต์ครั้งแรกในลำดับหนีเป็นค่า ASCII ESCซึ่งเป็นทศนิยม 27 และเลขฐานสิบหก0x1bในขณะทศนิยม 39 0x27เป็นเลขฐานสิบหก)


2
ปัญหาแรกในคำถามคือไม่มีช่องว่างรอบ=เครื่องหมายในการทดสอบดังนั้นจึงแยกวิเคราะห์เป็นสตริงที่ไม่ว่างเปล่าดังนั้นจึงเป็นเรื่องจริง ข้อเท็จจริงที่ว่าแป้นลูกศรมีหลายไบต์เป็นปัญหาที่แยกจากกัน
wurtel

2
อืมประโยคนั้นมีบริบทไม่มากเท่าที่ฉันเคยอ่านมาเพราะฉันคิดว่านั่นเป็นส่วนหนึ่งของคำอธิบายของลำดับหลายไบต์ที่ฉันรู้แล้ว
wurtel

2
@wurtel: ใช่ คลุมเครือฉันเดา พบว่าเมื่ออธิบาย[ได้หนึ่งคำสั่งในตัวคนจะเข้าใจว่าเหตุใดช่องว่างจึงสำคัญกว่าอย่างรวดเร็ว (ไม่ใช่วิธีทุบตีแปลก ๆ ที่จะใช้วงเล็บแทนวงเล็บ) ต้องหมดตอนนี้ อัปเดตอีกครั้ง
user367890
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.