如何在Bash中使用变量
什么是变量
变量是代表字符串或者数字值的命名符号。当我们在命令和表达式中使用它们时,会将它们视为我们键入了它们所拥有的值而不是变量名。
要创建变量,只需为其提供名称和值。变量名应具有描述性,并提醒我们它们所具有的价值。变量名不能以数字开头,也不能包含空格。但是,可以从下划线开始。除此之外,我们还可以混合使用大小写字母数字字符。
例子
在这里,我们将创建五个变量。格式是键入名称,等号" ="和值。请注意,等号前后没有空格。给变量赋值通常被称为为变量赋值。
我们将创建四个字符串变量和一个数字变量this_year:
me=Dave
my_boost=Linux
him=Popeye
his_boost=Spinach
this_year=2019
要查看变量中保存的值,请使用echo
命令。每当引用变量包含的值时,都必须在变量名称前加一个美元符号" $",如下所示:
echo $my_name
echo $my_boost
echo $this_year
让我们一次使用所有变量:
echo "$my_boost is to $me as $his_boost is to $him (c) $this_year"
变量的值替换其名称。我们还可以更改变量的值。要将新值分配给变量my_boost,只需重复分配第一个值时所做的操作,如下所示:
my_boost=Tequila
如果重新运行上一个命令,则现在将得到不同的结果:
echo "$my_boost is to $me as $his_boost is to $him (c) $this_year"
因此,如果更改变量中保存的值,则可以使用引用相同变量的相同命令并获得不同的结果。
稍后我们将讨论引用变量。现在,这里要记住一些事情:
单引号中的变量被视为文字字符串,而不是变量。
引号""中的变量被视为变量。
要获得变量中保存的值,必须提供美元符号" $"。
没有美元符号" $"的变量仅提供变量的名称。
我们还可以创建一个变量,该变量从现有变量或者多个变量中获取其值。以下命令定义了一个名为`drink_of_the_Year'的新变量,并为其分配了my_boost和this_year变量的组合值:
drink_of-the_Year="$my_boost $this_year"
echo drink_of_the-Year
如何在脚本中使用变量
没有变量,脚本将完全受阻。变量提供了使脚本成为通用而非特定解决方案的灵活性。为了说明不同之处,下面是一个脚本,该脚本对/ dev
目录中的文件进行计数。
将其键入文本文件,然后将其另存为fcnt.sh(用于文件计数):
#!/bin/bash folder_to_count=/dev file_count=$(ls $folder_to_count | wc -l) echo $file_count files in $folder_to_count
在运行脚本之前,必须使其成为可执行文件,如下所示:
chmod +x fcnt.sh
输入以下内容以运行脚本:
./fcnt.sh
这将打印/ dev
目录中的文件数。运作方式如下:
定义了一个名为
folder_to_count
的变量,并将其设置为容纳字符串/ dev。定义了另一个名为" file_count"的变量。此变量从命令替换中获取其值。这是括号" $()"之间的命令短语。请注意,在第一个括号之前有一个美元符号" $"。该结构$()计算括号内的命令,然后返回其最终值。在这个例子中,该值被分配给
file_count
变量。就file_count
变量而言,它传递了一个值来保存;它与如何获得价值无关。在命令替换中评估的命令会在" folder_to_count"变量(已设置为/ dev)中的目录上执行" ls"文件列表。因此,脚本执行命令/ dev。
该命令的输出通过管道传递到wc命令。 -l(行数)选项使wc对来自ls命令的输出中的行数进行计数。由于每个文件都在单独的行中列出,因此这是/ dev目录中文件和子目录的数量。这个值被分配给
file_count
变量。最后一行使用echo输出结果。
但这仅适用于/ dev目录。我们如何使脚本可以在任何目录下工作?只需做一个小改动。
如何在脚本中使用命令行参数
许多命令,例如ls和wc都带有命令行参数。这些为命令提供了信息,因此它知道我们要执行的操作。如果要使ls在主目录上工作并显示隐藏文件,则可以使用以下命令,其中波浪号~~和-a(all)选项是命令行参数:
ls ~ -a
我们的脚本可以接受命令行参数。第一个参数的引用为$ 1,第二个参数的引用为$ 2,依此类推,第九个参数的引用为$ 9. (实际上,也有一个" $ 0",但这是为了始终保存脚本而保留的。)
我们可以像常规变量一样在脚本中引用命令行参数。让我们修改脚本,如下所示,并用新名称fcnt2.sh
保存它:
#!/bin/bash folder_to_count= file_count=$(ls $folder_to_count | wc -l) echo $file_count files in $folder_to_count
这次,为" folder_to_count"变量分配了第一个命令行参数" $ 1"的值。
该脚本的其余部分与以前完全一样工作。现在,脚本已不再是一种特定的解决方案,而是一种通用的解决方案。我们可以在任何目录上使用它,因为它不是硬编码为仅与/ dev一起使用。
这是使脚本可执行的方式:
chmod +x fcnt2.sh
现在,尝试一些目录。我们可以先执行/ dev以确保获得与以前相同的结果。输入以下内容:
./fnct2.sh /dev
./fnct2.sh /etc
./fnct2.sh /bin
对于/ dev目录,我们将获得与以前相同的结果(207个文件)。这令人鼓舞,我们会获得其他每个命令行参数的特定于目录的结果。
为了缩短脚本,我们可以完全省去变量folder_to_count,而在整个过程中仅引用$ 1,如下所示:
#!/bin/bash file_count=$(ls wc -l) echo $file_count files in
使用特殊变量
我们提到了$ 0
,它总是设置为脚本的文件名。这使我们可以使用脚本来执行一些操作,例如正确重命名其名称。这在日志记录情况下很有用,在这种情况下,我们想知道添加条目的进程的名称。
以下是其他特殊的预设变量:
$#:向脚本传递了多少命令行参数。
$ @:传递给脚本的所有命令行参数。
$ ?:最后运行的进程的退出状态。
$$:当前脚本的进程ID(PID)。
$ USER:执行脚本的用户名。
$ HOSTNAME:运行脚本的计算机的主机名。
$ SECONDS:脚本已运行的秒数。
$ RANDOM:返回一个随机数。
$ LINENO:返回脚本的当前行号。
我们想在一个脚本中看到所有这些内容,不是吗?我们可以!将以下内容另存为名为" special.sh"的文本文件:
#!/bin/bash echo "There were $# command line parameters" echo "They are: $@" echo "Parameter 1 is: " echo "The script is called:chmod +x special.sh" # any old process so that we can report on the exit status pwd echo "pwd returned $?" echo "This script has Process ID $$" echo "The script was started by $USER" echo "It is running on $HOSTNAME" sleep 3 echo "It has been running for $SECONDS seconds" echo "Random number: $RANDOM" echo "This is line number $LINENO of the script"
输入以下内容使其可执行:
env | less
现在,我们可以使用许多不同的命令行参数来运行它,如下所示。
环境变量
Bash使用环境变量来定义和记录启动时创建的环境的属性。 Bash可以轻松访问这些保留信息,例如用户名,语言环境,历史文件可以保留的命令数量,默认编辑器等等。
要查看Bash会话中的活动环境变量,请使用以下命令:
#!/bin/bash first_var=alpha second_var=bravo # check their values echo "#!/bin/bash # check their values echo ": first_var=$first_var, second_var=$second_var" export first_var export second_var ./script_two.sh # check their values again echo "chmod +x script_one.sh chmod +x script_two.sh: first_var=$first_var, second_var=$second_var" # set new values first_var=charlie second_var=delta # check their values again echo "./script_one.sh: first_var=$first_var, second_var=$second_var"site_name=iGiftIdea: first_var=$first_var, second_var=$second_var"
如果我们在列表中滚动,可能会发现一些有用的脚本来引用。
如何导出变量
当脚本运行时,它在自己的进程中,并且在该进程之外无法看到其使用的变量。如果要与启动脚本的另一个脚本共享变量,则必须导出该变量。我们将通过两个脚本向我们展示如何做到这一点。
首先,使用文件名script_one.sh保存以下内容:
site_name="iGiftIdea"
这将创建两个变量" first_var"和" second_var",并分配一些值。它将这些打印到终端窗口,导出变量,并调用script_two.sh
。当" script_two.sh"终止时,处理流程返回该脚本,它将再次将变量输出到终端窗口。然后,我们可以查看它们是否更改。
我们将使用的第二个脚本是" script_two.sh"。这是script_one.sh调用的脚本。输入以下内容:
##代码##第二个脚本将打印两个变量的值,为它们分配新的值,然后再次打印它们。
要运行这些脚本,必须键入以下内容以使其可执行:
##代码##现在,键入以下内容以启动script_one.sh
:
这是输出告诉我们的:
script_one.sh打印变量的值,即alpha和bravo。
script_two.sh在接收变量时会输出它们的值(alpha和bravo)。
script_two.sh将它们更改为charlie和delta。
script_one.sh打印变量的值,它们仍然是alpha和bravo。
第二个脚本中发生的情况保留在第二个脚本中,就像变量的副本发送到第二个脚本中一样,但是当该脚本退出时它们被丢弃第一个脚本中的原始变量不会被第二个脚本中的副本所发生的任何更改。
如何引用变量
我们可能已经注意到,当脚本引用变量时,它们用引号""`引起。这允许正确引用变量,因此在脚本中执行该行时将使用它们的值。
如果我们分配给变量的值包含空格,则将它们分配给变量时,空格必须用引号引起来。这是因为,默认情况下,Bash使用空格作为定界符。
这是一个例子:
##代码##Bash将data之前的空格视为新命令正在启动的指示。它报告没有这样的命令,并放弃了这一行。 echo
向我们展示了site_name
变量不包含任何内容,甚至不包含操作方法文本。
再次尝试使用该值附近的引号,如下所示:
##代码##这次,它将被识别为单个值,并已正确分配给site_name
变量。