【问题标题】:Read a variable in bash with a default value使用默认值读取 bash 中的变量
【发布时间】:2011-02-08 05:06:31
【问题描述】:

我需要在 bash 脚本中从终端读取一个值。我希望能够提供用户可以更改的默认值。

# Please enter your name: Ricardo^

在此脚本中,提示是“请输入您的姓名:”,默认值为“Ricardo”,光标将位于默认值之后。有没有办法在 bash 脚本中做到这一点?

【问题讨论】:

    标签: bash shell


    【解决方案1】:
    read -e -p "Enter Your Name:" -i "Ricardo" NAME
    
    echo $NAME
    

    注意事项:

    • 此选项需要 bash 4 或更高版本 (bash --version)
    • 在 macOS 上,使用 homebrew 安装当前的 bash - brew.sh
    • -e-i 一起工作:-e 使用 readline-i 使用 readline 插入文本
    • bash 4+ manual page for read - linuxcommand.org

    【讨论】:

    • 很好的答案!我只想提一下我遇到了麻烦,因为我没有看到“Ricardo”和 NAME 之间的空格,但是一旦我弄清楚了……magic!谢谢!
    • 不幸的是 -i 不是 OSX 10.7 的有效选项
    • @BrianMortenson 您可以使用自制软件升级 bash:stackoverflow.com/questions/16416195/…
    • 这个答案展示了如何在 OS X (Bash 3.x) 上进行这项工作:stackoverflow.com/questions/22634065/…
    • 请注意,-e 似乎是必须的,以允许 -i 实际工作
    【解决方案2】:

    你可以使用parameter expansion,例如

    read -p "Enter your name [Richard]: " name
    name=${name:-Richard}
    echo $name
    

    在括号中的提示符中包含默认值是一种相当普遍的约定

    :-Richard 部分有什么作用?来自 bash 手册:

    ${parameter:-word} 如果参数未设置或为空,则替换单词的扩展。否则,参数的值被替换。

    另外值得注意的是...

    在以下每种情况下,单词都会受到波浪号扩展、参数扩展、命令替换和算术扩展的影响。

    所以如果你使用webpath=${webpath:-~/httpdocs},你会得到/home/user/expanded/path/httpdocs而不是~/httpdocs等的结果。

    【讨论】:

    • 我最终基于此做了一些事情。读入一个临时变量input,然后使用name=${input:-$name}
    • 这实际上并没有回答问题。默认值应该显示在提示符中。
    • name=${!input:-$name} 会做什么?
    • @Dr.PersonPersonII - 您可以通过执行以下操作添加默认值: read -p "Enter the remote host name [$remote_host_default]:" remote_host remote_host=${remote_host:-$remote_host_default }
    • $1 变为 ${1:-some_default_string}
    【解决方案3】:

    我刚刚使用了这种模式,我更喜欢:

    read name || name='(nobody)'
    

    【讨论】:

    • 我在 zsh 和 bash 上试过这个,但在任何一个 shell 中都不起作用。
    【解决方案4】:

    我发现了这个问题,正在寻找一种表达方式,例如:

    Something interesting happened.  Proceed [Y/n/q]:
    

    使用上面的例子我推断出:-

    echo -n "Something interesting happened.  "
    DEFAULT="y"
    read -e -p "Proceed [Y/n/q]:" PROCEED
    # adopt the default, if 'enter' given
    PROCEED="${PROCEED:-${DEFAULT}}"
    # change to lower case to simplify following if
    PROCEED="${PROCEED,,}"
    # condition for specific letter
    if [ "${PROCEED}" == "q" ] ; then
      echo "Quitting"
      exit
    # condition for non specific letter (ie anything other than q/y)
    # if you want to have the active 'y' code in the last section
    elif [ "${PROCEED}" != "y" ] ; then
      echo "Not Proceeding"
    else
      echo "Proceeding"
      # do proceeding code in here
    fi
    

    希望能帮助遇到同样问题的人不必思考逻辑

    【讨论】:

    • 非常好。如果有人只是输入“k”或给定选项以外的其他内容,甚至可以改进一点重复问题。
    • 我只是在抓痒之后写了这篇评论。我现在有一个 shell 函数,其中包括上述内容,并且我倾向于使用它。 Shell 似乎不能很好地循环,所以我尽量避免它。我可能会测试我的函数的结果,然后再试一次,但基本上,我正在编写可能出错的管理工具,所以我希望管理员能够在任何时候干净地停止脚本。
    【解决方案5】:
    #Script for calculating various values in MB
    echo "Please enter some input: "
    read input_variable
    echo $input_variable | awk '{ foo = $1 / 1024 / 1024 ; print foo "MB" }'
    

    【讨论】:

    • 请为您的答案添加解释。
    【解决方案6】:

    -e 和 -t 参数不能一起使用。我尝试了一些表达式,结果是以下代码 sn-p :

    QMESSAGE="SHOULD I DO YES OR NO"
    YMESSAGE="I DO"
    NMESSAGE="I DO NOT"
    FMESSAGE="PLEASE ENTER Y or N"
    COUNTDOWN=2
    DEFAULTVALUE=n
    #----------------------------------------------------------------#
    function REQUEST ()
    {
    read -n1 -t$COUNTDOWN -p "$QMESSAGE ? Y/N " INPUT
        INPUT=${INPUT:-$DEFAULTVALUE}
        if  [ "$INPUT" = "y" -o "$INPUT" = "Y" ] ;then
            echo -e "\n$YMESSAGE\n"
            #COMMANDEXECUTION
        elif    [ "$INPUT" = "n" -o "$INPUT" = "N" ] ;then
            echo -e "\n$NMESSAGE\n"
            #COMMANDEXECUTION
        else
            echo -e "\n$FMESSAGE\n"
        REQUEST
        fi
    }
    REQUEST
    

    【讨论】:

    • 你的回答与问题没有太大关系,不是吗?...
    • 它可以解决使用 -e 和 -t 参数的问题。此代码行(-e 和 -i 为默认值):读取 -e -p "Enter Your Name:" -i "Ricardo" NAME 不适用于倒数计时器(-t)
    • 是的,但问题中没有提到,是吗?
    • 你可以做的是提出一个新问题,然后自己回答;)。这是允许的! 但是我们不想用不相关的东西污染其他问题。
    【解决方案7】:

    代码:

    IN_PATH_DEFAULT="/tmp/input.txt"
    read -p "Please enter IN_PATH [$IN_PATH_DEFAULT]: " IN_PATH
    IN_PATH="${IN_PATH:-$IN_PATH_DEFAULT}"
    
    OUT_PATH_DEFAULT="/tmp/output.txt"
    read -p "Please enter OUT_PATH [$OUT_PATH_DEFAULT]: " OUT_PATH
    OUT_PATH="${OUT_PATH:-$OUT_PATH_DEFAULT}"
    
    echo "Input: $IN_PATH Output: $OUT_PATH"
    

    示例运行:

    Please enter IN_PATH [/tmp/input.txt]: 
    Please enter OUT_PATH [/tmp/output.txt]: ~/out.txt
    Input: /tmp/input.txt Output: ~/out.txt
    

    【讨论】:

    • 我喜欢这个,因为它遵循我在很多 shell 脚本中看到的约定,默认值在冒号前面的方括号中。谢谢!!!
    【解决方案8】:

    在 Bash 4 中:

    name="Ricardo"
    read -e -i "$name" -p "Please enter your name: " input
    name="${input:-$name}"
    

    这会在提示后显示名称,如下所示:

    Please enter your name: Ricardo
    

    将光标放在名称的末尾并允许用户对其进行编辑。最后一行是可选的,如果用户删除输入或默认值(提交 null),则强制名称为原始默认值。

    【讨论】:

    • 不能使用 bash4,因为它在 debian 发行版中是非标准的。我需要一些可以毫不费力地工作的东西。
    • 不需要最后一行代码,只需在read命令中使用name而不是input即可。
    • @RNAer:通过使用额外变量,如果用户删除建议的值(并因此输入空字符串),$name 的值将被保留。这完全取决于您的需求。我在回答中说了这么多。不过,你说得对,我本可以更明确地说,如果不使用可选行,那么变量可能是 name
    • @DennisWilliamson:你是对的。如果这是一个人想要的,这是一种很好的做法。
    【解决方案9】:
    name=Ricardo
    echo "Please enter your name: $name \c"
    read newname
    [ -n "$newname" ] && name=$newname
    

    设置默认值;打印它;读取一个新值;如果有新值,请使用它代替默认值。关于如何在提示符末尾取消换行符,shell 和系统之间存在(或曾经)一些差异。 '\c' 符号似乎适用于带有 3.x bash 的 MacOS X 10.6.3,并且适用于使用 Bourne 或 Korn shell 的从 System V 派生的大多数 Unix 变体。

    还要注意,用户可能不会意识到幕后发生的事情;他们的新数据将在屏幕上已经显示的名称之后输入。格式化它可能会更好:

    echo "Please enter your name ($name): \c"
    

    【讨论】:

    • printfecho 更便携
    • @ghostdog74:也许是这样;我们这些 25 年前学习 shell 编程的人很难弄清楚我们的哪些实践仍然适用。看起来 bash 已经重写了几乎所有内容。我知道 printf 作为命令已经存在了一段时间——不过,我很少使用它(可能——从来没有?)。我的印象是,在我(重新)学习 bash 之前,我应该对 shell 闭嘴。这很有趣;我使用的软件的 shell 脚本运行不佳 - 但问题不在于 bash-isms。我只是厌倦了修复 'if (test -z "$xxx"); ...' 和其他 C shellisms。
    • 我很惊讶 bash 支持\c,因为它也支持echo -n!但是,您必须添加 -e 才能获得 bash 的回声来解释转义。我猜\c 是用于未说明的事情:echo -e "Syntax slightly off\c, but I've learned so much from what you've shared. Thanks, @JonathanLeffler!"
    • @Jonathan Leffler 不幸的是,这并不是 OP 所要求的,至少在我的 bash 版本 4.x 上不是$ bash --version GNU bash, version 4.3.33(0)-release a) “我希望能够提供默认值用户可以更改的值。”您的 echo "Please enter your name: $name \c" 不允许我编辑默认值。 b)“并且光标将在默认值之后。”也不是真的……@Paused 的答案,直到另行通知。确实满足这两个要求。
    猜你喜欢
    • 1970-01-01
    • 2014-07-26
    • 2014-03-12
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 2011-01-02
    相关资源
    最近更新 更多