初始化Bash变量-随需应变,建议或定义


9

在将脚本中的bash变量的值赋给实际值之前,在主代码之前或在函数中的局部变量之前初始化脚本中的bash变量的值是否有任何优点/缺点?

我需要做这样的事情吗?

init()
{
    name=""
    name=$1
}

init "Mark"

是否存在使用垃圾值初始化变量(如果未初始化)以及对变量值产生负面影响的风险?


2
你从哪里得到这个主意的?

6
@DoritoStyle好吧,如果使用一种较低级别的语言(例如C),那么这是完全值得关注的事情。
库萨兰达

@Kusalananda的C语言不是该代码的等效语言name = ""; name = argv[1];吗?难道就没有意义吗?
约瑟夫·西布尔-恢复莫妮卡

1
@ JosephSible-ReinstateMonica是的。您发布的C代码毫无意义。但是,在C中,与在Shell中相反,未初始化的变量没有特定的定义明确的值。这意味着在许多情况下用C之类的语言初始化变量是有意义的。无需在外壳中执行此操作。如您所指出的,在C中初始化变量只是立即将其设置为另一个值是没有意义的。
库萨兰达

Answers:


22

将空字符串分配给变量,然后立即为其分配另一个变量字符串没有任何好处。将值分配给Shell变量将完全覆盖其先前的值。

据我所知,没有建议说应该将变量显式初始化为空字符串。实际上,这样做可能会掩盖某些情况下的错误(如果set -u在下运行,这些错误会很明显,请参阅下文)。

自脚本开始以来未使用过的未设置变量,或者通过在脚本上运行unset命令而未明确设置的未设置变量将没有任何值。这样的变量的值将为空。如果用作"$myvariable",您将获得的等效值"",并且您将永远不会获得“垃圾数据”。

如果将shell选项nounset设置为set -o nounsetset -u,则引用未设置的变量将导致Shell产生错误(并且非交互式Shell将终止):

$ set -u
$ echo "$myvariable"
/bin/sh: myvariable: parameter not set

或者,在bash

$ set -u
$ echo "$myvariable"
bash: myvariable: unbound variable

如果变量名称与现有的环境变量相对应,Shell变量将由环境初始化。

如果您希望使用的变量可以由环境以这种方式初始化(​​如果不需要的话),那么可以在脚本的主要部分之前显式取消设置它:

unset myvariable    # unset so that it doesn't inherit a value from the environment

这也将其删除为环境变量,或者,您可以简单地忽略其初始值,而仅用赋值覆盖它(这也会使环境变量更改值)。

您将永远不会在shell变量中遇到未初始化的垃圾(除非声明,除非该垃圾已经以相同的名称存在于环境变量中)。


3
虽然没有任何值可将变量​​设置为空值,然后立即按OP的方式进行设置,但在unset运行某种forwhile循环将其设置为计算值之前,先设置空值(或ting)是有价值的如果由于不满足条件而有可能使循环实际上无法运行的值;并且在脚本继承的环境中,该变量可能已设置为其他值。但是,最好将所有内容都放入a main()并将变量定义为local
蒙蒂·哈德

您还可以通过省略参数扩展运算符来检测未设置的变量:,例如${myvariable-defaultvalue}
Barmar

3

编辑:糟糕,声明显然与初始化不同。无论如何,我都会把它留在这里,以便像我这样的新手程序员可以从我的错误中学习。


在函数中声明局部变量的好处是您可以轻松地复制代码。

例如,说我有一个函数:

foo(){
    local name
    name="$1"
    echo "$name"
}

如果要将其制作为脚本,则只需忽略该local语句并复制其他所有内容:

#!/bin/bash
name="$1"
echo "$name"

如果声明和赋值在同一行中,那么我必须先手动将local零件编辑掉,然后才能将其转换为脚本:

foo(){
    local name="$1"
    echo "$name"
}

在此示例中,这没什么大不了的,但是如果您要处理更大,更复杂的功能,则可能会更加痛苦。


1
问题不在于结合声明和初始化。这是关于在分配实数之前是否用空值初始化。
Barmar

@Barmar哦,我只是查询了“初始化”。我认为这是“声明”的代名词...
wjandrea
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.