ZSH: la commande de lecture échoue dans la fonction bash "read: 1: -p: no coprocess"

29

Éditer:

Semble fonctionner à l'intérieur bash. Il semble que le problème soit lié à zsh. S'il existe un meilleur site pour publier ce problème, faites le moi savoir.


J'écris un script simple qui crée une série de répertoires. Je veux que l'utilisateur donne une confirmation avant de le faire. J'utilise ce qui suit comme base, mais je n'arrive pas à le faire fonctionner dans une fonction bash. Si je le mets en dehors d'une fonction, cela fonctionne bien. Voici un exemple isolé:

read.sh

#!/bin/bash
test() {
  read -p "Here be dragons. Continue?" -n 1 -r
  if [[ $REPLY =~ ^[Yy]$ ]]
  then
    echo "You asked for it..."
  fi
}

code de cette publication SO.

Sourcing le fichier et / ou les testrésultats de l'erreur suivante: read:1: -p: no coprocess. Même sortie lorsque je la place dans mon.bashrc

Modifier ::

@hennes

  1. Je veux que la fonction soit dans un fichier de configuration, donc je peux l'appeler à partir de n'importe quel répertoire (idéalement mon .bashrc ou .zshrc)
  2. J'ai corrigé le formatage de la première ligne commentée. Le problème existe toujours danszsh
  3. La version Bash est 3.2, mais vous m'avez aidé à comprendre que le problème est avec zsh et non bash.
Nick Tomlin
la source
1) Y a-t-il un endroit où vous appelez réellement la fonction test () ? 2) #! /bin/bashavec un espace derrière elle shebang? Je pensais que ce n'était pas autorisé? 3) '#! / Usr / bin / env bash' est probablement mieux. 4) Quelle version bash? (J'ai testé avec bash 4.1.10 sur FreeBSD et je n'ai eu aucune erreur)
Hennes
J'ai mal tagué la question, j'utilise zshmais je ne pensais pas qu'il y aurait un conflit avec les scripts bash (j'ai plusieurs autres scripts similaires en cours d'exécution). Je l'ai repensé et j'ai répondu à vos questions. Merci de m'avoir pointé dans la bonne direction!
Nick Tomlin
Comment démarrez-vous le programme? La ligne d'interpréteur shebang (#!) N'est nécessaire que si vous souhaitez exécuter le fichier avec ./read.sh. Ce n'est pas nécessaire si vous l'exécutez d'une autre manière ou si vous le mettez dans un script de démarrage. Et si vous voulez l'exécuter en zsh avec `zsh ./read.sh ', alors les lignes commençant par un # seront ignorées. Ils confondent également car ils donnent l'impression que vous utilisez bash lorsque vous utilisez zsh).
Hennes
@NickTomlin Savez-vous comment le faire fonctionner sans avoir à mettre Enter après «y» (sous ZSH)?
syntagma
@REACHUS hélas, je n'en ai pas. Bonne chance!
Nick Tomlin

Réponses:

50

L' –poption ne signifie pas la même chose bashest readintégré et commande zsh's read-commande intégrée. Dans zshla readcommande de, –psignifie –– devinez –– “L'entrée est lue à partir du coprocess.” Je vous suggère d'afficher votre invite avec echoou printf.

Vous devrez peut-être également remplacer –n 1par –kou –k 1.


L' zshéquivalent de bashl » read -p promptest -à-

read "?Here be dragons. Continue?"

Tout ce qui se trouve après a ?dans le premier argument est utilisé comme chaîne d'invite.

Et bien sûr, vous pouvez spécifier un nom de variable dans lequel lire (et cela peut être un meilleur style):

read "brave?Here be dragons. Continue?"
if [[ "$brave" =~ ^[Yy]$ ]]
then
    ...
fi

(La citation de variables shell est généralement une bonne idée également.)

Scott
la source
Merci d'avoir expliqué pourquoi cela ne fonctionne pas correctement. Je vérifierai des différences comme celle-ci à l'avenir.
Nick Tomlin
Excellente explication, merci!
Eu
8

Ce code semble faire ce que vous voulez dans zsh.
(Notez que la question à laquelle vous vous référez mentionne explicitement que c'est pour bash).

#! / usr / bin / env zsh

tester()
{
  echo -n "Voici des dragons. Continuez?"
  lire RÉPONSE

  si [[$ REPLY = ~ ^ [Yy] $]]
  ensuite
    echo "Vous l'avez demandé ..."
  Fi
}

tester

Trois commentaires:

Hennes
la source
Merci de votre aide. J'ai donné la réponse à @scott en raison de l'explication de la raison pour laquelle cela ne fonctionne pas, mais l'extrait de code que vous m'avez donné fonctionne parfaitement.
Nick Tomlin
1
Juste trois autres choses: il était probablement préférable de le poser sur SO (car c'est une question de programmation). 2) Tous les shells ne sont pas compatibles (man zsh retourne des choses différentes pour read -p puis man bash le fait. 3) Une autre solution serait de rechercher j pour vared -c -p 'prompt question'
Hennes
+1 Merci de m'avoir prévenu. Je dirigerai les futures questions centrées sur la programmation vers SO.
Nick Tomlin
Sur la dernière ligne de cette fonction, vous devez ajouter REPLY=""pour effacer la variable REPLY. Sinon, si vous faites écho à $ REPLY, vous verrez qu'il est toujours défini jusqu'à ce que vous ouvriez ou fermiez votre terminal ou le réinitialisiez.
jasonleonhard
0

Cette version vous permet d'avoir plus d'un cas you Y, nouN

  1. Facultativement: répétez la question jusqu'à ce qu'une question d'approbation soit fournie

  2. Facultativement: ignorer toute autre réponse

  3. En option: quittez le terminal si vous le souhaitez

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) echo 'nope n' ;;
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }

Remarquez cela aussi: sur la dernière ligne de cette fonction, effacez la variable REPLY. Sinon, si vous echo $REPLYle voyez, il est toujours réglé jusqu'à ce que vous ouvriez ou fermiez votre terminal ou le réinitialisiez.

jasonleonhard
la source