Shell 学习(5)Bash 变量

变量的类别

环境变量

已经在 Bash 环境中定义好的变量,Bash 自带的变量。可以直接使用,通常是系统定义好的。也可以由父 Shell 传入子 Shell。

环境变量很少改变,所以可以视为常量。名称都为大写,若想要自定义环境变量,尽量遵循这种命名规范。

查看已有的环境变量:

$ env
# 或者
$ printenv

下面是一些常见的环境变量的含义:

BASHPID:Bash 进程的进程 ID。
BASHOPTS:当前 Shell 的参数,可以用shopt命令修改。
DISPLAY:图形环境的显示器名字,通常是:0,表示 X Server 的第一个显示器。
EDITOR:默认的文本编辑器。
HOME:用户的主目录。
HOST:当前主机的名称。
IFS:词与词之间的分隔符,默认为空格。
LANG:字符集以及语言编码,比如zh_CN.UTF-8。
PATH:由冒号分开的目录列表,当输入可执行程序名后,会搜索这个目录列表。
PS1:Shell 提示符。
PS2: 输入多行命令时,次要的 Shell 提示符。
PWD:当前工作目录。
RANDOM:返回一个0到32767之间的随机数。
SHELL:Shell 的名字。
SHELLOPTS:启动当前 Shell 的set命令的参数,参见《set 命令》一章。
TERM:终端类型名,即终端仿真器所用的协议。
UID:当前用户的 ID 编号。
USER:当前用户的用户名。

查看指定的环境变量:

$ printenv PATH
$ echo $PATH
自定义变量

1、命令行中直接定义,随着当前 Shell 的结束(比如通过:exit 命令,或直接关闭终端窗口)而消失。

2、Shell script 文件中定义变量。相比较生命周期更短,当 Script 执行完毕后,变量就不存在了。可以先执行 Script 文件,在尝试在终端窗口中执行 echo ${varInScript} 进行输出测试。

创建变量

命名

如同其他开发语言一样,命名规则都是基本相同的。命名风格可以使用下面的几种常见的命名方式:

  1. 下划线:var_name
  2. 大驼峰:VarName
  3. 小驼峰:varName

因为我日常主要使用 Java 编程语言,后面编写 Shell 时统一使用小驼峰命名风格。

定义声明

variable=value,等号的左右不能有空格

值类型

Bash 中没有严格的数据类型的概念,所有的变量都是字符串。

a=z                     # 变量 a 赋值为字符串 z
b="a string"            # 变量值包含空格,就必须放在引号里面
c="a string and $b"     # 变量值可以引用其他变量的值
d="\t\ta string\n"      # 变量值可以使用转义字符
e=$(ls -l foo.txt)      # 变量值可以是命令的执行结果(支持扩展)
f=$((5 * 7))            # 变量值可以是数学运算的结果

读取变量

# 定义
$ myVar=C99

# 完整格式
$ echo "Hello ${myVar}"
Hello C99

# 简写(通过美元扩展符)
$ echo "Hello $myVar"
Hello C99

建议使用完整格式:

  1. 容易识别
  2. 更好的能被 Bash 读取

为什么说能更好的被 Bash 读取,如下面的例子:

$ echo "$100"
00

我们想输出一百美元的字符串,但输出了00。因为当读取一个不存在的变量时,Bash 会输出一个空字符串:'',所以输出了00

这种情况下需要在$符号前添加一个转义符\ 进行转义。那么为什么不按照完整的格式读取变量呢?即容易被识别意图,也可以避免这类问题。

还有一种情况,读取的变量的值是另一个变量的值:

$ myVar=C99
$ myVar2=myVar
$ echo ${myVar2}
myVar

输出结果不是最终值,可以:

$ echo ${!myVar2}
C99

${!varName} 其中的 ! 即读取终值的意思。

也可以在定义变量时,赋实际值:

$ myVar2=${myVar}

删除变量

$ unset myVar
$ myVar=''
$ myVar=

上面提到,若读取了一个不存在的变量时,会输出''。所以实际上,即使删除了变量,再次读取时依旧会有一个默认的''

导出变量(export 命令)

export 是一个内置命令:

$ type export
export is a shell builtin

在讨论该命令的功能前,强烈建议先看下Linux类下的环境变量 & 加强理解 Shell一文。

export 命令用于将变量输出为环境变量,或者将函数输出为环境变量。

用户创建的变量仅可用于当前 Shell,子 Shell 默认读取不到父 Shell 定义的变量。为了把变量传递给子 Shell,需要使用 export 命令。这样的变量,对于子 Shell 来说就是环境变量。

父、子 Shell 的概念在环境变量 & 加强理解 Shell一文中已进行了描述。这里在进行一次演示:

$ type -t bash
file
# 查看命令行窗口中的 Shell 进程 PID(30142)
$ ps -ef | grep bash
root      1769 30142  0 10:47 pts/0    00:00:00 grep --color=auto bash
root     30142 30138  0 10:28 pts/0    00:00:00 -bash

# 或者通过上面提到的环境变量: BASHPID 查看当前命令行窗口中的 Shell 进程 PID
$ echo ${BASHPID}
30142

# 新启一个 Shell 进程
$ bash

# 查看 Shell 进程信息(PID 为1801的 Shell 进程的 PPID 正为30142)
$ ps -ef | grep bash
root      1801 30142  1 10:47 pts/0    00:00:00 bash
root      2006  1801  0 10:48 pts/0    00:00:00 grep --color=auto bash
root     30142 30138  0 10:28 pts/0    00:00:00 -bash

# 通过环境变量 BASHPID 查看子 Shell 进程 PID
$ echo ${BASHPID}
1801

# 退出当前 Shell 进程
$ exit
exit

# 再次查看 Shell 进程信息
$ ps -ef | grep bash
root      2979 30142  0 10:52 pts/0    00:00:00 grep --color=auto bash
root     30142 30138  0 10:28 pts/0    00:00:00 -bash

语法:

# 第一种方式
NAME=C99
export NAME

# 第二种方式
export NAME=C99

测试:

# 定义一个普通变量 与 一个导出变量
$ MY_VAR1=C99
$ export MY_VAR2=C999

# 启动一个子 Shell 进程
$ bash

# 在子 Shell 进程中分别输出上面的两个变量
$ echo ${MY_VAR1}

$ echo ${MY_VAR2}
C999

特殊变量

Bash 提供的一些特殊变量,这些变量的值由 Bash 进行控制,用户不能改变。

1、$?:上一个执行命令的退出码,可以用来判断上一个执行命令是否执行成功:0 success、非0 failure

$ ls ./
test.sh

$ echo $?
0

$ ls noexists
ls: cannot access noexists: No such file or directory

$ echo $?
2

2、$$:当前 Shell 进程的 PID

$ echo $$
2790

# 输出环境变量进行复验
$ echo ${BASHPID}
2790

3、$_:上一个命令的最后一个参数

$ echo A B C
A B C

$ echo $_
C

4、$!:最近一个后台异步执行的命令的进程 PID

# '&' 符号可以使命令后台异步执行
$ echo A B C &
[1] 9554
A B C

$ echo $!
9554
[1]+  Done   echo A B C

5、$0:输出当前 Shell 的名称

命令行环境中输出

$ echo $0
-bash

Shell Script 文件中输出

Script 文件内容:

#!/bin/bash

echo $0

执行:

$ ./test.sh 
./test.sh

6、$-:当前 Shell 的启动参数

$ echo $-
himBH

himBH 每个字母都是一个 Shell 启动参数,具体含义可以搜索查询一下。

7、$@、$#、$N(number)

  1. $#表示脚本的参数数量
  2. $@表示脚本的参数值
  3. $N表示第N个 Shell 执行参数(第0个默认为 Shell script 文件名称)
#!/bin/bash

echo $@
echo $#

echo $0
echo $1
echo $2
echo $3
$ ./test.sh p1 p2
全部参数: p1 p2
参数数量: 2
第0个参数: ./test.sh
第1个参数: p1
第2个参数: p2
第3个参数: 

变量的默认值

  1. ${varName:-defVal}:变量存在且不为空,返回变量值。否则返回默认值(用于保证返回值不为空)。
  2. ${varName:=defVal}:变量存在且不为空,返回变量值。否则设置默认值(用于设置默认值)。
  3. ${varName:+defVal}:变量存在且不为空,返回默认值。否则返回空(用于校验变量是否存在)。
  4. ${varName:?message}:变量存在且不为空,返回变量值。否则中断 Script 执行,并输出 message。如果不指定 message,默认输出:varName: parameter null or not set(用于参数断言)

上面四种取默认值的语法,在 Script 执行中时,若获取的是 Script 启动参数,可以用1 - 9来代替。比如:

  1. ${1:?message}:Script 第一个参数不存在即中止执行,并提示指定的错误信息。
  2. ${2:-defVal}:Script 第二个参数不存在则返回默认值。

declare 命令

用于将普通变量改为特殊变量,为变量增加一些特性。比如声明变量为只读的。

语法:

declare OPTION VARIABLE=value

主要参数(OPTION)如下:

1、-a:声明数组变量。

2、-f:输出所有函数(含实现)。

3、-F:输出所有函数名。

4、-i:声明整数变量。参数声明整数变量以后,可以直接进行数学运算。

$ declare -i tempVar
$ var1=1
$ var2=2
$ tempVar=var1+var2
$ echo ${tempVar}
3

我们仅需要将接收结果的变量设置为整数变量,不需要对所有参与运算的变量设置为整数变量

如果不设定为整数变量,仅会进行值拼接,而不是进行运算。

5、-l:声明变量值为小写字母。

$ declare -l var1=LOWER
$ echo ${var1}
lower
$ var1=LOWER
$ echo ${var1}
lower

6、-u:声明变量为大写字母。

$ declare -u var1=upper
$ echo ${var1}
UPPER
$ var1=upper
$ echo ${var1}
UPPER

7、-r:声明只读变量。

$ declare -r var1
$ var1=upper
-bash: var1: readonly variable
$ unset var1
-bash: unset: var1: cannot unset: readonly variable

8、-x:导出变量为环境变量。

$ declare -x var1
# 等同于
$ export var1

9、-p:查看变量信息。

$ declare -rux var1=upper
$ declare -p var1
declare -rxu var1="UPPER"

若 declare 命令如果用在函数中,声明的变量只在函数内部有效,等同于 local 命令。

若不带任何参数时,declare 命令输出当前环境的所有变量,包括函数在内,等同于不带有任何参数的 set 命令。

readonly 命令

等同于declare -r,用来声明只读变量,不能改变变量值,也不能 unset 变量。

三个参数:

  1. -f:定义只读函数。
  2. -a:定义只读数组变量。
  3. -p:显示系统中全部只读变量列表。
$ readonly var1

# 实际上就是对变量添加了 -r 属性
$ declare -p var1
declare -r var1="1"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值