ZSH: Der Lesebefehl schlägt in der Bash-Funktion "read: 1: -p: no coprocess" fehl

29

Bearbeiten:

Scheint zu funktionieren bash. Es scheint, dass das Problem damit zusammenhängt zsh. Wenn es eine bessere Seite gibt, auf der Sie dieses Problem veröffentlichen können, lassen Sie es mich wissen.


Ich schreibe ein einfaches Skript, das eine Reihe von Verzeichnissen erstellt. Ich möchte, dass der Benutzer eine Bestätigung gibt, bevor ich dies tue. Ich verwende das Folgende als Basis, kann es jedoch nicht innerhalb einer Bash-Funktion ausführen. Wenn ich es außerhalb einer Funktion platziere, funktioniert es gut. Hier ist ein isoliertes Beispiel:

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 aus diesem SO Post.

Sourcing die Datei und / oder testErgebnisse in dem folgenden Fehler: read:1: -p: no coprocess. Gleiche Ausgabe, wenn ich es in meine.bashrc

Bearbeiten :

@hennes

  1. Ich möchte, dass sich die Funktion in einer Konfigurationsdatei befindet, damit ich sie aus einem beliebigen Verzeichnis aufrufen kann (idealerweise aus meiner .bashrc- oder .zshrc-Datei).
  2. Ich habe die Formatierung der ersten kommentierten Zeile korrigiert. Problem besteht immer noch inzsh
  3. Die Bash-Version ist 3.2, aber Sie haben mir geholfen herauszufinden, dass das Problem mit zsh und nicht mit bash zusammenhängt.
Nick Tomlin
quelle
1) Gibt es eine Stelle, an der Sie den Funktionstest () aufrufen ? 2) #! /bin/bashmit einem Leerzeichen hinter ihr? Ich dachte das wären nicht erlaubt? 3) '#! / Usr / bin / env bash' ist wahrscheinlich besser. 4) Welche Bash-Version? (Ich testete mit Bash 4.1.10 auf FreeBSD und bekam keine Fehler)
Hennes
Ich habe die Frage falsch getaggt, aber ich habe zshnicht gedacht, dass es einen Konflikt mit Bash-Skripten geben würde (ich habe mehrere ähnliche Skripten, die in Ordnung sind). Ich habe es erneut markiert und auf Ihre Fragen geantwortet. Danke, dass du mich in die richtige Richtung gelenkt hast!
Nick Tomlin
Wie starte ich das Programm? Die shebang (#!) Interpreter-Zeile wird nur benötigt, wenn Sie die Datei mit ausführen möchten ./read.sh. Es wird nicht benötigt, Sie führen es auf andere Weise aus oder wenn Sie es in ein Startskript einfügen. Und wenn Sie es in zsh mit `zsh ./read.sh 'ausführen möchten, werden die mit einem # beginnenden Zeilen ignoriert. Sie sind auch verwirrend, da sie den Eindruck erwecken, dass Sie bash verwenden, wenn Sie zsh verwenden.
Hennes
@NickTomlin Weißt du, wie es funktioniert, ohne dass die Eingabetaste nach 'y' (unter ZSH) gesetzt werden muss?
Syntagma
@ REACHUS leider nicht. Viel Glück!
Nick Tomlin

Antworten:

49

Die –pOption bedeutet nicht das Gleiche zu bash‚s readintegriertes Kommando und zsh‘ s readintegrierten Befehl. In zsh's readKommando –pbedeutet - rate - "Eingabe wird aus dem Coprozess gelesen." Ich schlage vor, dass Sie Ihre Eingabeaufforderung mit echooder anzeigen printf.

Sie können auch ersetzen müssen –n 1mit –koder –k 1.


Das zshÄquivalent von bash‚s read -p promptIS

read "?Here be dragons. Continue?"

Alles nach einem ?im ersten Argument wird als Eingabeaufforderungszeichenfolge verwendet.

Und natürlich können Sie einen Variablennamen angeben, in den eingelesen werden soll (und dies könnte einen besseren Stil haben):

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

(Das Zitieren von Shell-Variablen ist im Allgemeinen auch eine gute Idee.)

Scott
quelle
Vielen Dank für die Erklärung, warum dies nicht richtig funktioniert. Ich werde in Zukunft nach solchen Unterschieden suchen.
Nick Tomlin
Tolle Erklärung, danke! Hatte genau das gleiche Problem
iosifv
8

Dieser Code scheint in zsh zu tun, was Sie wollen.
(Beachten Sie, dass in der Frage, auf die Sie sich bezogen haben, ausdrücklich erwähnt wird, dass es sich um eine Bash handelt.)

#! / usr / bin / env zsh

Prüfung()
{
  echo -n "Hier sind Drachen. Weiter?"
  Lesen Sie ANTWORT

  if [[$ REPLY = ~ ^ [Yy] $]]
  dann
    echo "Du hast danach gefragt ..."
  fi
}

Prüfung

Drei Kommentare:

Hennes
quelle
Danke für deine Hilfe. Ich habe @scott die Antwort gegeben, weil erklärt wurde, warum dies nicht funktioniert, aber das Snippet, das Sie mir gegeben haben, funktioniert einwandfrei.
Nick Tomlin
1
Nur noch drei Dinge: Dies wurde wahrscheinlich am besten auf SO gestellt (da es sich um eine Programmierfrage handelt). 2) Nicht alle Shells sind kompatibel (man zsh gibt andere Dinge für read -p zurück als man bash. 3) Eine andere Lösung wäre, nach vared -c -p 'prompt question' zu suchen
Hennes
+1 Danke, dass du mich informiert hast. Ich werde zukünftige programmierbezogene Fragen an SO richten.
Nick Tomlin
In der letzten Zeile dieser Funktion sollten Sie hinzufügen REPLY="", um die Variable REPLY zu löschen. Wenn Sie andernfalls $ REPLY wiederholen, wird angezeigt, dass es noch gesetzt ist, bis Sie Ihr Terminal öffnen oder schließen oder es erneut setzen.
Jasonleonhard
0

Mit dieser Version können Sie mehr als einen Fall haben , yoder Y, noderN

  1. Optional: Wiederholen Sie die Frage, bis eine Genehmigungsfrage bereitgestellt wird

  2. Optional: Ignorieren Sie jede andere Antwort

  3. Optional: Verlassen Sie das Terminal, wenn Sie möchten

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

Beachten Sie auch dies: Löschen Sie in der letzten Zeile dieser Funktion die Variable REPLY. Andernfalls echo $REPLYbleibt die Einstellung bestehen, bis Sie das Terminal öffnen, schließen oder erneut einstellen.

jasonleonhard
quelle