Shell 变量
1. Shell 变量概述
变量是任何程序或脚本的重要组成部分,变量为程序或脚本访问内存中的可的一块数据提供了简单的方式。
Linux Shell 中的变量可以被指定为任意的数据类型,比如文本字符串或者数值。你也可以通过 Shell 中的变量来改变 Shell 的样式。
接下来就让我们来了解和学习一下 Shell 中的变量吧。
Shell 变量是什么呢,顾名思义,就是可以变化的量,如果有编程基础的读者知道任何程序中都有变量,从我们小时候做数学题,定义的 x 变量,最终给定值,用值替换 x 变量,这就是我们最初接触的变量,它和我们在 Shell 中接触的变量本质上是一致的。
变量在 Shell 中是存储计算器内存的单元,其中存放的值可以改变,当我们在编写 Shell 脚本中,如果一些经常用的字符串或数字我们就可以定义变量,将具体的值赋给这个变量,然后在具体的或脚本中引用这个变量,就相当于拿到了这个值。
我们大概了解了 Shell 变量是什么,那么为什么在 Shell 脚本中需要变量呢?
例如在 Shell 脚本中,我们需要指定目录,脚本内多处了这个目录,现在我们有个需求目录改变了,我们该怎么办呢,在脚本中每个使用该目录的地方都需要改成新的目录,有没有简单的只需要改一处地方呢,这时候就用到了我们的变量,在脚本的全局定义变量例如 BASE_DIR
,然后将目录赋值给这个变量,在具体引用的时候利用这个目录的变量,下次需要我们改,只用改最前面这个变量即可。
因此我们使用变量就是为了方便,同时也使得我们的脚本更具灵活性扩展性与后期的可维护性。
2. Shell 变量基本操作
我们知道了 Shell 中变量是什么以及其在 Shell 编写中的重要性,那么让我们先来学习 Shell 变量的基本操作。
在使用 Shell 变量前,需要先定义变量,定义变量的方式有三种:
顾名思义就是直接将值赋值给变量,这种需要注意值中不能包含空白字符
例如:正确的直接赋值变量:DIR=/tmp
,其中 DIR
为变量名,/tmp
为值
的直接赋值:STRING=hello Shell
,其中 STRINNG
为变量名,hello Shell
为值,其中值包含了空白字符,这种赋值变量就是的。
如果值中为普通字符,那么单引号赋值与双引号赋值没有区别,其可以包含空白字符,但是如果其中包含了变量的使用,那么单引号赋值方式为单引号里面的是什么就什么,此种赋值方式适用于不希望解析变量的场景,仅纯字符串。
例如:
[root@master ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin[root@master ~]# DIR='$PATH'[root@master ~]# echo $DIR$PATH[root@master ~]# DATE='$(date)'[root@master ~]# echo $DATE$(date)
PATH
为 linux 系统内置的环境变量,DIR 为我们定义的变量,值为单引号引起来的 $PATH
,查看其也为 $PATH
,同理对于执行 date
命令。
与单引号赋值一样,其也可以包含空白字符,但是与单引号赋值不同的是,双引号赋值可以解析引号内的变量或执行命令,即不是将双引号中的变量名和命令原样,而是解析其中变量的,然后进行。
例如:
[root@master ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin[root@master ~]# DIR="$PATH"[root@master ~]# echo $DIR/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin[root@master ~]# DATE="$(date)" [root@master ~]# echo $DATE Sun Mar :: CST
可以通过与单引号示例对照查看,双引号赋值解析了 PATH
变量的值然后,同理对于执行命令 date
。
我们知道了变量的定义方式,那么该如何使用变量呢?使用变量非常简单,只需要在定义的变量名前面 $
即可使用定义的变量
例如:
[root@master ~]# DIR=/tmp[root@master ~]# echo $DIR/tmp
在使用变量中有一种特殊情况,需要我们手动指定变量的边界是什么,此时就需要使用到 {}
。
[root@master ~]# STRING="hello Shell"[root@master ~]# echo "test $STRINGtest"test [root@master ~]# echo "test ${STRING}test"test hello Shelltest
通过示例我们能够看出,不使用 {}
引起来变量,如果变量名后面继续有字符,Shell 无法判断我们的变量边界在哪里,我们推荐在使用变量的时候都带上 {}
减少出错的概率,并且方便我们人为识别变量的边界。
我们已经定义了变量,如果对变量进行更新呢,更新变量重新赋值即可
例如:
[root@master ~]# DIR=/tmp[root@master ~]# echo $DIR/tmp[root@master ~]# DIR=/root[root@master ~]# echo $DIR/root
另外在变量中存在只读变量,顾名思义其为定义好后,只能只读,不能对其进行,使用 readonly 命令可以将变量定义为只读变量
[root@master ~]# readonly STRING="Shell"[root@master ~]# echo ${STRING}Shell[root@master ~]# STRING="test"-bash: STRING: readonly variable[root@master ~]# echo ${STRING}Shell
可以看到我们使用 readonly 定义变量后,对变量进行时候报错,只读变量无法进行。
变量的使用 unset,后就消除了定义的变量,变量被后不能再次使用;unset 命令不能只读变量。
例如
[root@master ~]# DIR=/tmp [root@master ~]# echo "dir is ${DIR}" dir is /tmp[root@master ~]# unset DIR[root@master ~]# echo "dir is ${DIR}" dir is
3. Shell 变量规范
与其他语言一样,Shell 中变量也需要遵循一定的规范,
变量命名只能使用,数字和下划线,首字母不能以数字开头
正常变量:BASE_DIR
,File_Name
,AEG3
,_DIR
等都是正常的变量
无效变量:1file
,#dir
例如
变量名中间不能使用空格或
例如:DIR FILE
,DIR?FILE
就为无效变量
变量命名不能使用 base 里面的关键字(help 来查看关键字)
Shell 变量大小写敏感,也就是定义为大写的变量名,引用的时候必须完全一致。
例如:DIRNAME
和 dirname
就是两个不同的变量
变量与值直接使用 “=” 连接,等号两边不能存在空白字符;
例如: dirname = "/tmp"
赋值就是的。
如果值中有空白字符,使用单引号或双引号引起来,双引号对于其中引用的值将会根据其转化,单引号内的特殊字符则一律当字符串进行处理;
例如:DIRNAME="$PATH"
的值为系统 PATH 实际的可执行路径,DIRNAME='$PATH'
的值为 $PATH 的字符串。
可用 \
来转译变量,让其变为一般字符;
例如:DIRNAME=\$PATH
的值为 $PATH 的字符串。
如果变量的值为指令,可用使用反撇号,或 $() 来引用;
例如:下面两个是一样的
DATE=`date`DATE=$(date)
在脚本中定义普通字符串变量时,应尽量把变量的用双引号括起来;
例如:DIRNAME="/tmp"
单纯数字的变量可以不加引号;
例如:NUM=10
4. 变量的
Shell 的变量有三种,每种都有其不同的作用范围
局部变量,顾名思义其只在 Shell 脚本中定义的变量,或在 Shell 脚本中定义的变量,只能在 Shell 脚本中使用,或只能在 Shell 脚本中使用
例如:
[root@master Shell]# cat local_var.sh #!/bin/bashDIR=/tmp echo "dir is ${DIR}"[root@master Shell]# bash local_var.sh dir is /tmp[root@master Shell]# echo "dir is ${DIR}"dir is
我们可以看出在脚本内部定义的变量 DIR
只在 local_var
脚本内可以使用,在全局下没有此变量,后期我们学到再来说明中的局部变量。
环境变量为当前 Shell 中定义的临时变量,在当前 Shell 定义的变量可以传递给子 Shell,没有父子关系的 Shell 不能使用此变量,当然可以利用 export
将当前 Shell 的变量传递给其他终端的 Shell 中。
当前 Shell 为父 Shell,在其上运行 bash
就可以进入到子 Shell 中,让我们来看示例
# 在当前Shell中定义变量STR[root@master Shell]# STR="Shell" [root@master Shell]# echo "hello ${STR}"hello Shell# 运行命令bash进入子Shell[root@master Shell]# bash# 在子Shell中查看没有STR[root@master Shell]# echo "hello ${STR}"hello # 子Shell回到父Shell[root@master Shell]# exitexit# 利用export导入环境变量[root@master Shell]# export STR="Shell"# 在此进入子Shell[root@master Shell]# bash# 查看子Shell中已经有了变量STR[root@master Shell]# echo "hello ${STR}"hello Shell
环境变量为临时的,在我们启动终端的时候,系统会从特定的中加载一系列环境变量。
系统中还有一些系统内置的变量,例如 PATH
,USER
等,我们可以利用命令 env 或 export 来查看当前 Shell 的环境变量,例如:
[root@master Shell]# envXDG_SESSION_ID=HOSTNAME=master SELINUX_ROLE_REQUESTED=Shell=/bin/bash TERM=xterm HISTSIZE=SSH_CLIENT=. SELINUX_USE_CURRENT_RANGE=SSH_TTY=/dev/pts/USER=root...# 查看当前Shell[root@master Shell]# echo $Shell/bin/bash# 查看可执行命令的路径[root@master Shell]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin# 查看当前系统[root@master Shell]# echo $USERroot
linux 系统的一些内置参数
$Shell 认 Shel$HOME 当前家目录$IFS 内部字段分隔符$LANG 认语$PATH 认可执行程序路径$PWD 当前目录$UID 当前 ID$USER 当前$HISTSIZE 历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间$RANDOM 0 至 32767 的整数$HOSTNAME 主机名
为在当前 Shell 进程中运行的脚本都可以使用该变量,在 Shell 中认定义的变量就是,例如:
[root@master Shell]# cat global_var1.sh #!/bin/bashecho "${STR1}"# 查看STR1变量的STR2="sh"# 定义STR2变量的值为sh[root@master Shell]# cat global_var2.sh #!/bin/bashecho "${STR2}"# 查看STR2变量的[root@master Shell]# STR1="Shell" [root@master Shell]# . ./global_var1.sh Shell[root@master Shell]# . ./global_var2.sh sh
我们可以看出利用.
来运行 Shell 脚本,是在当前的 Shell 终端中运行,其变量是在当前 Shell 进程中可以共享的。
5. 实例
我们通过简单编写当前信息的脚本,来展示目前的信息
[root@master Shell_var]# cat login_info.sh #!/bin/bash# Description: login info scripts# Auth: kaliarch# Email: kaliarch@163.com# function: show user info# Date: 2020-03-08 13:36# Version: 1.0echo "当前系统用为: ${USER}"echo "当前系统时间: $(date +"%Y-%m-% %H:%M:")"echo "当前系统Shell: ${Shell}"echo "当前家目录为: ${HOME}"# 运行脚本查看[root@master Shell_var]# bash login_info.sh 当前系统用为: root 当前系统时间: -- :: 当前系统Shell: /bin/bash 当前家目录为: /root
6. 注意事项
在引用变量是我们遵守规范,带上 {}
,可以避免不必要的麻烦和坑;
命名变量见名知意,形成有自己一套的命名规范;
学习 Shell 需要多动手实践,将变量的三种类型通过实践真正理解,后期在编写 Shell 的时候可以灵活运用。
7. 小结
变量在我们 Shell 编程中的有这独特的地位,其将我们的一些数据通过一次性的赋值,大大增强了脚本的灵活性与后期可维护性。我们需要通过本章节充分理解 Shell 的基本操作及其种类,在编写 Shell 中灵活运用,遵循定义及使用规范,可以使得我们编写的 Shell 更加友好及健壮。