在bash中读取具有默认值的变量


191

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

# Please enter your name: Ricardo^

在此脚本中,提示为“请输入您的名称:”,默认值为“里卡多”,光标将位于默认值之后。有什么办法可以在bash脚本中做到这一点?

Answers:


278

您可以使用参数扩展,例如

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

在方括号之间的提示中包括默认值是很常见的约定


7
我最终基于此做了一些事情。读入一个临时变量input,然后使用name=${input:-$name}
Ricardo Marimon

41
这实际上并不能回答问题。默认值应显示在提示中。
Person Person II博士,

3
怎么name=${!input:-$name}办?
哈里·李

8
@ Dr.PersonPersonII-您可以通过执行以下操作来添加默认值:读取-p“输入远程主机名[$ remote_host_default]:” remote_host remote_host = $ {remote_host:-$ remote_host_default}
Dobler

4
$1成为${1:-some_default_string}
ThorSummoner '16

159
read -e -p "Enter Your Name:" -i "Ricardo" NAME

echo $NAME

1
好答案!我只想提一下我遇到了麻烦,因为我看不到“里卡多”和NAME之间的空格,但是一旦我弄清楚了…… 魔术!谢谢!
MIKKEL先生

40
不幸的是-i对于OSX 10.7不是有效的选项
undefined

3
:@BrianMortenson可以升级庆典使用自制stackoverflow.com/questions/16416195/...
antonagestam

2
这个答案显示了如何使OS X(猛砸3.X)这项工作:stackoverflow.com/questions/22634065/...
克里斯托夫Petschnig

3
请注意,-e似乎必须强制性的才能-i实际工作
MestreLion

48

在Bash 4中:

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

这样会在提示符后显示名称:

Please enter your name: Ricardo

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


无法使用bash4,因为它在debian发行版中是非标准的。我需要可以轻松解决的问题。
Ricardo Marimon

1
不需要最后一行代码,只需在命令中使用name而不是。inputread
RNA

1
@RNAer:通过使用额外的变量,$name如果用户删除建议的值(并因此输入空字符串),则将保留的值。这完全取决于您的需求。我在回答中说了很多。没错,不过,我本来可以更明确地说,如果不使用可选行,则变量可以是name
暂停,直到另行通知。

1
@DennisWilliamson:你是对的。如果那是一个好习惯,那是一个好习惯。
RNA

16

码:

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脚本中看到的约定,其中默认值在冒号之前的方括号中。谢谢!!!
morphetic

16

我发现了这个问题,寻找一种呈现类似内容的方法:

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”或除给定选择以外的其他内容,则可以重复该问题,甚至可以稍作改进。
erikbwork

1
我只是在痒痒之后写了这个评论。我现在有一个shell函数,其中包括上述内容,并且我倾向于使用它。Shell似乎循环不好,所以我尽量避免这种情况。我可能会测试函数的结果,然后再尝试一次,但是基本上,我正在编写可能会出错的管理工具,因此我希望管理员能够随时干净地停止脚本。
sibaz'4

11

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

read name || name='(nobody)'

6
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 Shells在从System V派生的Unix的大多数变体上运行。

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

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

printf比更便携echo
ghostdog74

3
@ ghostdog74:也许是这样;我们这些在25年前学习了Shell编程的人很难确定我们的哪些实践仍然有意义。bash似乎几乎已重写了所有内容。我知道printf作为命令已经存在了一段时间-尽管(可能-从来没有?),我很少使用它。我得到的印象是,在我重新学习bash之前,应该关闭shell。'很有趣;我使用的软件具有无法正常运行的Shell脚本-但问题不是bash-isms。我只是厌倦了修复' if (test -z "$xxx"); ...'和其他C shell行为。
乔纳森·莱夫勒

我对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!"
jpaugh

1
#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" }'

3
请在回答中添加解释。
Sufiyan Ghori,2015年

-1

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

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

您的答案与问题没有多大关系,对吗?…
gniourf_gniourf 2014年

它可以解决使用-e和-t参数的问题。此代码行(-e和-i为默认值):读取-e -p“输入您的名称:” -i“里卡多”名称不适用于倒数计时器(-t)
speefak

是的,但这不是问题所在,对吗?
gniourf_gniourf 2014年

3
您可以做的是提出一个新问题,然后自己回答;)。这样就可以了!但是我们不想用无关的内容污染其他问题。
gniourf_gniourf 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.