【问题标题】:How can I prompt for yes/no style confirmation in a zsh script?如何在 zsh 脚本中提示是/否样式确认?
【发布时间】:2013-02-16 22:07:05
【问题描述】:

使用 zsh,我试图在我的 ~/.zprofile 中迈出一步,在那里我以交互方式询问是/否风格问题。一开始我尝试了this bash-style approach,但是我看到了这种形式的错误:

read: -p: no coprocess

(我知道 zsh 语法通常与 bash 不同 - 我尝试在它前面加上一个 sh 仿真命令 - emulate -LR sh - 但没有区别)。

这个页面暗示语法可能不同,所以在 this page 和 zsh 手册页的指导下,我尝试了这个:

read -q REPLY?"This is the question I want to ask?"

这反而会因为以下形式的错误而失败:

/home/user/.zprofile:5: no matches found: REPLY?"This is the question I want to ask?"

如何使用 zsh 提出一个简单的是/否问题?理想情况下,该命令只会吞下一个字符,无需按 Enter/Return,并且是“安全”的 - 即后续测试默认为 no/false,除非输入“Y”或“y”。

【问题讨论】:

    标签: bash scripting zsh prompt


    【解决方案1】:

    来自zsh - read

    如果第一个参数包含“?”,则该单词的其余部分将在 shell 交互时用作标准错误提示。

    你必须引用整个论点

    read -q "REPLY?This is the question I want to ask?"
    

    这将提示您This is the question I want to ask? 并返回REPLY 中按下的字符。

    如果您不引用问号,zsh 会尝试将参数匹配为文件名。如果它没有找到任何匹配的文件名,它会抱怨no matches found

    【讨论】:

      【解决方案2】:

      有关 ZSH 读取的文档,请参阅 ZSH Manual。试试:

      read REPLY\?"This is the question I want to ask?"
      

      【讨论】:

        【解决方案3】:

        我添加此答案是因为每次您想要求用户确认时,您也想对其采取行动。这是一个以read -q 提示的函数(谢谢,其他答案!)并在结果上进行分支以执行您想要的操作(在这种情况下,是 git 的东西):

        git_commit_and_pull() {
            # http://zsh.sourceforge.net/Doc/Release/Shell-Builtin-Commands.html#index-read
            if read -q "choice?Press Y/y to continue with commit and pull: "; then
                git add . && git commit -m 'haha git goes brrr' && git pull
            else
                echo
                echo "'$choice' not 'Y' or 'y'. Exiting..."
            fi
        }
        

        【讨论】:

          【解决方案4】:

          我为此创建了两个实用程序脚本:

          • read-string.sh 从输入中读取字符串(需要用户按回车键)
          • read-char.sh 从输入中读取单个字符(不需要按回车键)

          无论用户使用的是 bash 还是 zsh,这两个脚本都能正常工作。

          #!/bin/bash
          # read-string.sh
          # eg: my_string=$(./read-string.sh); echo "my_string: $my_string"
          
          # bash `read` manual - https://ss64.com/bash/read.html
          # 
          # read [-ers] [-a aname]  [-d delim] [-i text] [-n nchars]
          #    [-N nchars] [-p prompt] [-r] [-s] [-t timeout] [-u fd]
          #       [name...]
          # 
          #  -r        Do not treat a Backslash as an escape character.  The backslash is considered to be part
          #            of the line. In particular, a backslash-newline pair can not be used as a line continuation.
          #            Without this option, any backslashes in the input will be discarded.
          #            You should almost always use the -r option with read.
          
          # zsh `read` manual - http://zsh.sourceforge.net/Doc/Release/Shell-Builtin-Commands.html#index-read
          # 
          # read [ -rszpqAclneE ] [ -t [ num ] ] [ -k [ num ] ] [ -d delim ]
          #     [ -u n ] [ name[?prompt] ] [ name ... ]
          # 
          # -r         Raw mode: a ‘\’ at the end of a line does not signify line continuation and backslashes in the line
          #            don’t quote the following character and are not removed.
          
          if [ -n "$ZSH_VERSION" ]; then
            read -r "answer?"
          else
            read -r answer
          fi
          echo "$answer"
          
          #!/bin/bash
          # eg: my_char=$(read-char.sh); echo "my_char: $my_char"
          
          # bash `read` manual - https://ss64.com/bash/read.html
          # 
          # read [-ers] [-a aname]  [-d delim] [-i text] [-n nchars]
          #    [-N nchars] [-p prompt] [-r] [-s] [-t timeout] [-u fd]
          #       [name...]
          # 
          #  -r        Do not treat a Backslash as an escape character.  The backslash is considered to be part
          #            of the line. In particular, a backslash-newline pair can not be used as a line continuation.
          #            Without this option, any backslashes in the input will be discarded.
          #            You should almost always use the -r option with read.
          #  -n nchars read returns after reading nchars characters rather than waiting for a complete line of input.
          
          # zsh `read` manual - http://zsh.sourceforge.net/Doc/Release/Shell-Builtin-Commands.html#index-read
          # 
          # read [ -rszpqAclneE ] [ -t [ num ] ] [ -k [ num ] ] [ -d delim ]
          #     [ -u n ] [ name[?prompt] ] [ name ... ]
          # 
          # -q         Read only one character from the terminal and set name to ‘y’ if this character was ‘y’ or ‘Y’
          #            and to ‘n’ otherwise. With this flag set the return status is zero only if the character was ‘y’ or ‘Y’.
          #            This option may be used with a timeout (see -t); if the read times out, or encounters end of file,
          #            status 2 is returned. Input is read from the terminal unless one of -u or -p is present.
          #            This option may also be used within zle widgets.
          # -r         Raw mode: a ‘\’ at the end of a line does not signify line continuation and backslashes in the line
          #            don’t quote the following character and are not removed.
          
          if [ -n "$ZSH_VERSION" ]; then
            read -r -q "answer?"
          else
            read -r -n 1 answer
          fi
          echo "$answer"
          

          感谢Olaf 他的original answer

          【讨论】:

            猜你喜欢
            • 2012-02-12
            • 2010-12-25
            • 2021-02-02
            • 1970-01-01
            • 1970-01-01
            • 2022-06-14
            • 2010-09-18
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多