8
votes

Bash Scripting - Read Keystroke unique, y compris les clés spéciales Entrée et espace

Je ne sais pas si je devrais mettre ceci sur Stackoverflow ou Unix.stackexchange, mais j'ai trouvé des Similaire Questions ici, alors ça va .

J'essaie de créer un script à appeler par .CASHRC qui me permet de sélectionner l'une des deux options en fonction d'une seule frappe. Ce ne serait pas difficile normalement, mais je veux que les deux clés correspondant aux deux options soient d'espace et d'entrer. P>

Voici ce que j'ai jusqu'à présent: P>

:~$ bin/sessionSelect.sh
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//0
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//0
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//1
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug/x/1


3 Réponses :


3
votes
#!/bin/bash
SELECT=""
# prevent parsing of the input line
IFS=''
while [[ "$SELECT" != $'\x0a' && "$SELECT" != $'\x20' ]]; do
  echo "Select session type:"
  echo "Press <Enter> to do foo"
  echo "Press <Space> to do bar"
  read -s -N 1 SELECT
  echo "Debug/$SELECT/${#SELECT}"
  [[ "$SELECT" == $'\x0a' ]] && echo "enter" # do foo
  [[ "$SELECT" == $'\x20' ]] && echo "space" # do bar
done

4 commentaires

ifs = '' n'est pas requis. Read -n retournera l'entrée tel quel, ignorant IFS (voir la page de l'homme). Testé ceci sans ifs = '' , fonctionne bien. Très bonne réponse! Utilisé cela pour implémenter ma propre version de '-More--'.


@Maxxim Cela pourrait être dans une version de bash nouvelle. Au moins pour Centos 7.6 avec Bash-4.2.46 (2), le ifs = '' est requis.


Vous avez raison. Le changement a été introduit dans Bash 4.4 . Dans la page man sur lecture -n NCHARS , ce qui suit a été ajouté: [...] Le résultat n'est pas divisé sur les caractères de l'IFS; L'intention est que la variable est affectée exactement aux caractères lus (à l'exception de la barre oblique inverse; voir l'option -r ci-dessous). Souhaitez-vous modifier votre réponse et signalerait les autres?


@Maxxim basé sur ce (non officiel) Liste des modifications , il est difficile de dire Comment exactement l'instance Bash donnée se comporte (il y avait beaucoup de bugs avec le traitement IFS). N'oubliez pas non plus de Backporting .



2
votes

Il y a quelques choses sur lisez qui sont pertinentes ici:

  • Il lit une seule ligne
  • La ligne est divisée en champs comme avec la fractionnement de mots

    Puisque vous lisez un personnage, cela implique que la saisie de entrer entraînerait une variable vide.

    En outre, par des règles par défaut pour la fractionnement de mots, Saisie de espace entraînerait également une variable vide. La bonne nouvelle est que vous pouvez gérer cette partie en réglant ifs .

    modifier votre lecture instruction à: xxx < / pré>

    et attendez-vous à une chaîne nulle au lieu de $ '\ x0a' lorsque vous entrez entrez .


1 commentaires

Cela fonctionne également et avec la définition des IFS uniquement pour la commande de lecture est essentiellement aussi propre une solution. J'ai toujours marqué Putnynhill comme le bon, car il ne peut pas produire d'effets secondaires accidentels à travers une modification des IFS. Upvoté cependant! BTW, avec -N au lieu de -n sélectionner n'est pas vide lors de l'envoi d'entrée mais contient réellement la valeur attendue.



4
votes

Essayez de définir le délimiteur de lecture à une chaîne vide, puis vérifiez la variable de réponse intégrée $:

read -d'' -s -n1


4 commentaires

Cela fonctionne bien, même sans changer le délimiteur avec -D. Les deux entrées et l'espace sont correctement détectés.


Nous avons probablement des saveurs différentes de lire . Si je laisse de côté -d '', je ne reçois pas la clé Entrée.


Je viens de remarquer que nous utilisons -n et -n respectivement. Cela doit être la raison de cela, lors de la spécification de la longueur avec des nouvelles lignes, ne sont pas traités spécialement.


J'allais tester avec l'option -N, mais ma lecture ne l'a pas.