Imprime as chaves atualmente pressionadas para stdout e as lê linha por linha

5

Eu quero saber quais teclas são pressionadas no meu teclado e imprimir as informações no stdout.

Uma ferramenta que pode fazer isso é showkey . No entanto, se eu quiser passar os dados de showkey para read :

while read line; do
  echo "$line" | otherprog
done <'showkey -a'

OR

showkey -a | while read line; do
  echo "$line" | otherprog
done

Em seguida, showkey espera até que uma soma de 140 caracteres seja digitada e, em seguida, envia as informações em buffer para read .

showkey -a imprime as teclas pressionadas linha por linha, sem qualquer buffer.

  1. Por que ele armazena em buffer?
  2. Como evito esse armazenamento em buffer, para que eu possa ler verdadeiramente a saída de showkey linha por linha?
  3. Existe uma alternativa para showkey ?
  4. Existe algum arquivo no qual eu possa ler as teclas pressionadas diretamente?
  5. Qual é a maneira correta de passar dados para read ?

Solução:

Eu usei a solução da lornix e a incluí no meu teclado simples: D!

stdbuf -o0 showkey -a | while read line; do
  perl -e 'print sprintf "%030s\n",shift' "$line" | aplay &> /dev/null &
done

Versão do Lasership:

#!/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

Na mesma pasta, faça o download de alguns arquivos de mp3 a laser em uma pasta chamada mp3 .

    
por polym 14.07.2014 / 03:19

2 respostas

4

Tente definir showkey output como não-buffer com o comando stdbuf :

stdbuf -o0 showkey -a | cat -

mostrará a saída conforme as teclas são pressionadas, em vez de armazenar em buffer uma linha.

stdbuf pode ajustar o armazenamento em buffer de stdin , stdout e stderr , definindo-os para nenhum , buffer de linha ou bloco buffered , com um tamanho de bloco selecionável. Muito útil.

    
por 14.07.2014 / 07:58
4

Ele armazena em buffer porque seu terminal está configurado para uma disciplina de linha orientada por linha. Você precisa de stty raw . Tente isto:

state=$(stty -g) 
key=$( (stty raw ; dd bs=1 count=1; stty $state) </dev/tty 2>/dev/null) 

Mas isso só funcionará para pressionamentos de tecla de byte único. Pode ser uma boa ideia fazer LC_ALL=C primeiro se houver uma chance de que a entrada possa conter os kepresses de vários bytes. Um exemplo mais sofisticado pode parecer mais com isso:

{   exit=$(printf '
state=$(stty -g) 
key=$( (stty raw ; dd bs=1 count=1; stty $state) </dev/tty 2>/dev/null) 
3') 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
    
por 14.07.2014 / 03:52

Tags