0

I have a script that aims to find out which key is pressed. The problem is that I don't manage it quickly because I need the timeout in the fifth digit that makes it not react quickly, or not react at all.

#!/bin/bash
sudo echo Start
while true
do
    file_content=$(sudo timeout 0.5s cat /dev/input/event12 | hexdump)
    content_split=$(echo $file_content | tr " " "\n")
    word_counter=0
    for option in $content_split
    do
        word_counter=$((word_counter+1))
        if [ $word_counter -eq 25 ]
        then
            case $option in
                "0039")echo "<space>";;
                "001c")echo "<return>";;
                "001e")echo "a";;
                "0030")echo "b";;
                "002e")echo "c";;
                "0020")echo "d";;
                "0012")echo "e";;
                "0021")echo "f";;
                "0022")echo "g";;
                "0023")echo "h";;
                "0017")echo "i";;
                "0024")echo "j";;
                "0025")echo "k";;
                "0026")echo "l";;
                "0032")echo "m";;
                "0031")echo "n";;
                "0018")echo "o";;
                "0019")echo "p";;
                "0010")echo "q";;
                "0013")echo "r";;
                "001f")echo "s";;
                "0014")echo "t";;
                "0016")echo "u";;
                "002f")echo "v";;
                "0011")echo "w";;
                "002d")echo "x";;
                "002c")echo "y";;
                "0015")echo "z";;
            esac
        fi
    done
done
3
  • 2
    Please write in English, not German. Commented Mar 25, 2021 at 13:19
  • I think using timeout in the first place is the root of both of your problems. There may be a way you can use something like tail or read to read the events "live". Commented Mar 25, 2021 at 13:39
  • running timeout in the first place is wrong. You want to do work with a stream, so parse input in a steaming fashion - in pseudocode cat /dev/input/event12 | while read_one_byte; do parse_one_byte; done. Do not run it periodically - that's conceptually invalid.. Commented Mar 25, 2021 at 14:32

1 Answer 1

3

Do not run cat in a timeout in a loop - that's just an invalid way to look at the problem. No matter how "fast" your program runs it will always miss some events that way. Overall polling approach is just invalid here.

The parsing and linux philosophy is build around streams that transfers bytes. The always available streams are stdin, stdout and stderr. They allow to pass data from one context to another. The shell most common | operator allows to bind together output from one program to input of another program - and this is the way™ you should work in shell. Shell primary use is to "connect" programs together.

So you could do:

# read from the input
sudo cat /dev/input/mouse1 |
# transform input to hex data one byte at at time so 
# we could parse it in **shell**
xxd -c1 -p |
# read one byte and parse it in **shell**
while IFS= read -r line; do
    : parse line
done

but shell is very slow and while read is very slow. If you want speed (and events from input are going to be fast) do not use shell and use a good programming language - python, perl, ruby, at least awk - these are common scripting languages. The case $option in construct looks like a mapping from hex values to output strings. I could see:

# save one `cat` process by just calling xxd
sudo xxd -c1 -p dev/input/mouse1 |
awk 'BEGIN{
         map["1c"]="<return>";
         map["1e"]="a";
        # etc. add all other cases to mapping
     }
     { if ($0 in a) print map[$0] }
'
Sign up to request clarification or add additional context in comments.

1 Comment

i used shel only because i want to learn bash normally i code in java or python

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.