我想知道键盘上按下了哪些键并将信息打印到标准输出。
可以做到这一点的工具是showkey
.但是,如果我想将数据传递showkey
给read
:
while read line; do
echo "$line" | otherprog
done <`showkey -a`
或者
showkey -a | while read line; do
echo "$line" | otherprog
done
然后showkey
等待,直到输入 140 个字符的总和,然后将缓冲的信息发送到read
。
showkey -a
逐行打印按下的按键,没有任何缓冲。
- 为什么会缓冲?
- 如何避免这种缓冲,以便我可以
showkey
真正逐行读取输出? - 有替代方案吗
showkey
? - 是否有一个文件可以直接读取按下的按键?
- 将数据传递到的正确方法是什么
read
?
解决方案:
我用过洛尼克斯的解决方案并将其包含到我的简单键盘中:D!
stdbuf -o0 showkey -a | while read line; do
perl -e 'print sprintf "%030s\n",shift' "$line" | aplay &> /dev/null &
done
激光飞船版本:
#!/bin/bash
MP3=(); for i in mp3/*.mp3; do MP3+=("$i"); done
NMP3=${#MP3[@]}
stdbuf -o0 showkey -a 2>/dev/null | while read line; do
[ -z "$line" ] || ! [[ $line =~ ^[0-9] ]] && continue
NUM="$(echo "$line" | awk '{print $2}')"
mplayer "${MP3[$(($NUM % $NMP3))]}" &>/dev/null &
done
在同一个文件夹中,下载一些激光mp3文件放入名为 的文件夹中mp3
。
答案1
尝试showkey
使用以下命令将输出设置为非缓冲stdbuf
命令:
stdbuf -o0 showkey -a | cat -
将在按下按键时显示输出,而不是缓冲一行。
stdbuf
stdin
可以调整、stdout
和的缓冲stderr
,将它们设置为没有任何,行缓冲, 或者块缓冲,具有可选择的块大小。非常便利。
答案2
它会缓冲,因为您的终端设置为面向行的行规则。你需要stty raw
。尝试这个:
state=$(stty -g)
key=$( (stty raw ; dd bs=1 count=1; stty $state) </dev/tty 2>/dev/null)
但这仅适用于单字节按键。LC_ALL=C
如果输入有可能包含多字节 kepresses,那么首先执行此操作可能是个好主意。一个更复杂的例子可能看起来更像这样:
{ exit=$(printf '\003')
tty_state=$(stty -g)
stty raw istrip
while key=$(
dd bs=1 count=1
) ; do : "${key:=
}"; printf " %03o %03d %#x\n\r" \
"'$key" "'$key" "'$key"
[ -z "${key#"$exit"}" ] && {
stty "$tty_state"
break
}
done 2>/dev/null
} </dev/tty