ZSH: el comando de lectura falla dentro de la función bash "read: 1: -p: no coprocess"

29

Editar:

Parece trabajar dentro bash. Parece que el problema está relacionado con zsh. Si hay un sitio mejor para publicar este problema, avíseme.


Estoy escribiendo un script simple que crea una serie de directorios. Quiero que el usuario dé una confirmación antes de hacerlo. Estoy usando lo siguiente como base, pero parece que no puedo ejecutarlo dentro de una función bash. Si lo pongo fuera de una función, funciona bien. Aquí hay un ejemplo aislado:

leer.sh

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

código de esta publicación SO.

Abastecimiento del archivo y / o testresultados en el siguiente error: read:1: -p: no coprocess. Misma salida cuando lo coloco en mi.bashrc

Editar :

@hennes

  1. Quiero que la función esté en un archivo de configuración, para poder llamarla desde cualquier directorio (idealmente mi .bashrc o .zshrc)
  2. He corregido el formato de la primera línea comentada. El problema aún existe enzsh
  3. La versión Bash es 3.2, pero me has ayudado a descubrir que el problema es con zsh y no bash.
Nick Tomlin
fuente
1) ¿Hay algún lugar donde realmente llame a la función test () ? 2) #! /bin/bashcon un espacio detrás de ella shebang? Pensé que no estaban permitidos? 3) '#! / Usr / bin / env bash' es probablemente mejor. 4) ¿Qué versión de bash? (Probé con bash 4.1.10 en FreeBSD y no obtuve errores)
Hennes
Etiqueté incorrectamente la pregunta, la estoy usando zshpero no pensé que habría conflicto con los scripts de bash (tengo varios otros scripts similares ejecutándose correctamente). Lo volví a etiquetar y respondí a tus preguntas. ¡Gracias por señalarme en la dirección correcta!
Nick Tomlin
¿Cómo comienzas el programa? La línea de intérprete shebang (#!) Solo es necesaria si desea ejecutar el archivo con ./read.sh. No es necesario si lo ejecuta de otra manera o si lo coloca en un script de inicio. Y si desea ejecutarlo en zsh con `zsh ./read.sh ', las líneas que comienzan con un # se ignoran. También confunden ya que dan la impresión de que usas bash cuando usas zsh).
Hennes
@NickTomlin ¿Sabes cómo hacerlo funcionar sin tener que poner Enter después de 'y' (bajo ZSH)?
syntagma
@REACHUS por desgracia, no lo hago. ¡Buena suerte!
Nick Tomlin

Respuestas:

49

La –popción no significa lo mismo que bash's readcomando integrado y zsh' s readcomando integrado. En zshel readcomando, –psignifica –– adivinar –– “La entrada se lee desde el coproceso”. Sugiero que muestre su solicitud con echoo printf.

También es posible que deba reemplazar –n 1con –ko –k 1.


El zshequivalente de bash's read -p promptes

read "?Here be dragons. Continue?"

Cualquier cosa después de a ?en el primer argumento se utiliza como cadena de solicitud.

Y, por supuesto, puede especificar un nombre de variable para leer (y este puede ser un mejor estilo):

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

(Citar variables de shell es generalmente una buena idea también).

Scott
fuente
Gracias por la explicación de por qué esto no funciona correctamente. Comprobaré diferencias como esta en el futuro.
Nick Tomlin
Gran explicación, gracias! Tuve exactamente el mismo problema
iosifv
8

Este código parece hacer lo que quieres en zsh.
(Tenga en cuenta que la pregunta que mencionó explícitamente es para bash).

#! / usr / bin / env zsh

prueba()
{
  echo -n "Aquí hay dragones. ¿Continuar?"
  leer RESPUESTA

  si [[$ REPLY = ~ ^ [Yy] $]]
  luego
    echo "Lo pediste ..."
  fi
}

prueba

Tres comentarios:

Hennes
fuente
Gracias por tu ayuda. Le di la respuesta a @scott debido a la explicación de por qué esto no funciona, pero el fragmento que me has dado funciona perfectamente.
Nick Tomlin
1
Solo tres cosas más: probablemente esto se hizo mejor en SO (ya que es una pregunta de programación). 2) No todas las conchas son compatibles (retornos hombre zsh diferentes cosas para leer -p entonces el hombre hace bash 3) Otra solución sería searchj para vared -c -p 'pregunta requerimiento'.
Hennes
+1 Gracias por hacérmelo saber. Dirigiré futuras preguntas centradas en la programación a SO.
Nick Tomlin
En la última línea de esta función, debe agregar REPLY=""para borrar la variable REPLY. De lo contrario, si repite $ REPLY, verá que todavía está configurado hasta que abra o cierre su terminal o lo configure de nuevo.
jasonleonhard
0

Esta versión le permite tener más de un caso yo Y, noN

  1. Opcionalmente: repita la pregunta hasta que se proporcione una pregunta de aprobación

  2. Opcionalmente: ignore cualquier otra respuesta

  3. Opcionalmente: salga de la terminal si lo desea

    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=''
    }

Observe esto también: en la última línea de esta función, borre la variable REPLY. De lo contrario, si echo $REPLYverá que todavía está configurado hasta que abra o cierre su terminal o lo configure de nuevo.

jasonleonhard
fuente