ZSH: Сбой команды чтения в bash-функции «read: 1: -p: no coprocess»

29

Редактировать:

Кажется, работает внутри bash. Похоже, проблема связана с zsh. Если есть лучший сайт для публикации этой проблемы, дайте мне знать.


Я пишу простой скрипт, который создает серию каталогов. Я хочу, чтобы пользователь дал подтверждение, прежде чем я это сделаю. Я использую следующее в качестве основы, но не могу заставить его работать внутри функции bash. Если я помещу это вне функции, это работает отлично. Вот отдельный пример:

read.sh

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

код из этого поста.

Sourcing файла и / или testрезультатов в следующей ошибке: read:1: -p: no coprocess. Тот же вывод, когда я помещаю его в мой.bashrc

Редактировать ::

@hennes

  1. Я хочу, чтобы функция была в конфигурационном файле, поэтому я могу вызывать ее из любого каталога (в идеале мой .bashrc или .zshrc)
  2. Я исправил форматирование первой закомментированной строки. Проблема все еще существует вzsh
  3. Версия Bash 3.2, но вы помогли мне понять, что проблема в zsh, а не в bash.
Ник Томлин
источник
1) Есть ли место, где вы на самом деле вызываете функцию test () ? 2) #! /bin/bashс пробелом сзади она шебанг? Я думал, что это не разрешено? 3) «#! / Usr / bin / env bash», вероятно, лучше. 4) Какая версия Bash? (Я тестировал bash 4.1.10 на FreeBSD и не получил ошибок)
Hennes
Я неправильно пометил вопрос, который я использую, zshно не думал, что возникнет конфликт со скриптами bash (у меня есть несколько других похожих скриптов, работающих нормально). Я пометил его и ответил на ваши вопросы. Спасибо, что указал мне правильное направление!
Ник Томлин
Как вы запускаете программу? Строка интерпретатора shebang (#!) Необходима только в том случае, если вы хотите выполнить файл с помощью ./read.sh. В этом нет необходимости, вы запускаете его любым другим способом или помещаете в сценарий запуска. И если вы хотите запустить его в zsh с помощью `zsh ./read.sh ', тогда строки, начинающиеся с #, игнорируются. Они также сбивают с толку, так как создают впечатление, что вы используете bash, когда используете zsh).
Хенн
@NickTomlin Знаете ли вы, как заставить его работать без необходимости вводить Enter после 'y' (под ZSH)?
синтагма
@REACHUS Увы, я не знаю. Удачи!
Ник Томлин

Ответы:

50

–pВариант не означает , что то же самое с bash«S readвстроенная команда и zsh» s readвстроенную команду. В zsh«S readкоманды, –pзначит - догадка -„Input считывается из coprocess.“Я полагаю , что вы показываете ваше приглашение с echoили printf.

Вам также может понадобиться заменить –n 1на –kили –k 1.


zshЭквивалент bash«ы read -p promptесть

read "?Here be dragons. Continue?"

Все, что находится после ?первого аргумента, используется в качестве строки приглашения.

И, конечно, вы можете указать имя переменной для чтения (и это может быть лучше стиль):

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

(Кавычки переменных оболочки, как правило, тоже хорошая идея.)

Скотт
источник
Спасибо за объяснение того, почему это не работает должным образом. Я буду проверять наличие различий в будущем.
Ник Томлин
Отличное объяснение, спасибо! Была точно такая же проблема
iosifv
8

Этот код, кажется, делает то, что вы хотите в Zsh.
(Обратите внимание, что в вопросе, на который вы ссылались, он явно упоминается как bash).

#! / usr / bin / env zsh

тестовое задание()
{
  echo -n "Будь драконами. Продолжить?"
  читать ОТВЕТИТЬ

  если [[$ REPLY = ~ ^ [Гг] $]]
  тогда
    echo "Ты просил об этом ..."
  фи
}

тестовое задание

Три комментария:

Hennes
источник
Спасибо за помощь. Я дал ответ @scott из-за объяснения того, почему это не работает, но фрагмент, который вы мне дали, работает отлично.
Ник Томлин
1
Еще три вещи: это, вероятно, лучше всего задавать на SO (так как это вопрос программирования). 2) Не все оболочки совместимы (man zsh возвращает разные вещи для чтения -p, тогда как man bash делает. 3) Другим решением было бы поискать vared -c -p 'быстрый вопрос'
Hennes
+1 Спасибо, что дали мне знать. Я буду направлять будущие вопросы по программированию в SO.
Ник Томлин
В последней строке этой функции вы должны добавить REPLY=""очистить переменную REPLY. В противном случае, если вы откроете $ REPLY, вы увидите, что он все еще установлен, пока вы не откроете или не закроете свой терминал или не установите его снова.
Джейсон Леонард
0

Эта версия позволяет вам иметь более одного случая yили Y, nилиN

  1. Дополнительно: повторяйте вопрос до тех пор, пока не будет предоставлен вопрос для утверждения.

  2. Опционально: игнорировать любой другой ответ

  3. Опционально: выйдите из терминала, если хотите

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

Обратите внимание и на это: в последней строке этой функции очистите переменную REPLY. В противном случае, если вы echo $REPLYувидите, что он все еще установлен, пока вы не откроете или не закроете свой терминал или не установите его снова.

jasonleonhard
источник