Bash脚本中的提示不显示参数

时间:2015-04-20 12:41:21

标签: bash shell

我有以下代码:

#!/bin/sh

g_yes=0
g_no=-1
g_cancel=1
g_none=127

show_yes_no_prompt()
{
        rc=$g_none
        prompt=$*
        while true; do
                read -p $prompt"(ync): "
                case $yn in
                        [Yy]* ) rc=$g_yes; break;;
                        [Nn]* ) rc=$g_no; break;;
                        [Cc]* ) rc=$g_cancel; break;;
                        * ) echo "Please answer yes/no/cancel.";;
                esac
        done
        return $rc
}

install_pkg()
{
        pkg_name=$*
        prompt="Install "$pkg_name"?"
        show_yes_no_prompt $prompt
        if [ $? -eq $g_cancel ]; then
                exit 0
        fi
        if [ $? -eq $g_yes ]; then
                apt-get install -y $pkg_name
        else
                echo "Installation of "$pkg_name" refused."     
        fi
}

当我写install_pkg package1 package2时,提示只会显示'Install',但我需要提示符如'Install package1 package2'。那么,这段代码出了什么问题?

2 个答案:

答案 0 :(得分:1)

这是错误的界限:

read -p $prompt"(ync): "

$prompt包含空格,因此read只会占用$prompt的第一个单词。解决方案是将$prompt括在"中,以确保它是一个完整的字符串。

替换为

read -p "$prompt (ync): " yn

通常,在bash中对字符串使用"时,您可以直接使用变量。无需拆分字符串。如果您不想要空格,可以像下面这样限制变量的名称:

read -p "${prompt}(ync): " yn

答案 1 :(得分:1)

你引用的事情都很混乱。您想引用变量扩展。

所以你想要prompt="Install $pkg_name?"show_yes_no_prompt "$prompt"等,而不是prompt="Install "$pkg_name"?"show_yes_no_prompt $prompt

这里发生的事情是,您将$prompt的每个单词作为单独的参数传递给show_yes_no_prompt(这很好,因为您将它们全部粘贴到$*一起虽然注意到你无法以这种方式正确处理名称中包含空格的包,但是该函数。

问题是当你在函数中使用$prompt而不引用它时它会再次被分开,因此read的{​​{1}}参数只看到第一个单词,并显示它显示的全部(然后由于-p不是有效的标识符而被你的“变量名称”弄糊涂了。

您也不会将pkg(ync)作为参数读取,因此它不会将其读取的值分配给那里。

脚本的更正版本如下。

yn

注意我是如何使用数组在#!/bin/sh g_yes=0 g_no=-1 g_cancel=1 g_none=127 show_yes_no_prompt() { rc=$g_none while true; do read -r -p "$* (ync): " yn case $yn in [Yy]* ) rc=$g_yes; break;; [Nn]* ) rc=$g_no; break;; [Cc]* ) rc=$g_cancel; break;; * ) echo "Please answer yes/no/cancel.";; esac done return $rc } install_pkg() { pkgs=("$@") show_yes_no_prompt "Install ${pkgs[*]}?" if [ $? -eq $g_cancel ]; then exit 0 fi if [ $? -eq $g_yes ]; then apt-get install -y "${pkgs[@]}" else echo "Installation of ${pkgs[*]} refused." fi } 函数中存储$@的。这是正确/安全地处理任意包名称的唯一方法。

install_pkg的{​​{1}}参数几乎总是您想要的,并阻止-r解释/吞咽反斜杠转义。

另请注意,一般情况下,read扩展比read扩展更可取(并应始终引用),除非将扩展放在需要单个字符串的字符串中例如@扩展是必要的。)

另请注意,您永远不会从函数中获取*。你会得到*