在Shell中包括有三种变量类型:系统环境变量、自定义变量和特殊符号变量。
系统环境变量是系统提供的共享变量,是linux系统加载Shell的配置文件中定义的变量共享给所有的Shell程序使用。环境变量按照其作用范围不同大致可以分为系统级环境变量和用户级环境变量。
Shell的配置文件分类:
环境变量加载初始化过程:
/etc/profile
、/当前用户/.bash_profile
/当前用户/.bashrc
、/etc/bashrc
查看当前Shell环境:
1 | echo $0 |
---|
输出-bash
表示shell登录环境,输出bash
表示shell非登录环境。注意:这个 $0
环境变量如果用在子shell中(shell脚本文件)输出Shell脚本本身的文件名。
切换shell环境:
直接切换用户
12345 | #切换到指定用户,加载Shell登录环境变量su 用户名 --login #或 su 用户名 -l# 切换到指定用户,加载Shell非登录环境变量su 用户名 |
---|
切换Shell环境执行脚本文件
123456 | #先加载Shell登录环境流程初始化环境变量, 再执行脚本文件sh/bash -l/--login 脚本文件#先执行加载Shell非登录环境流程初始化环境变量, 再执行脚本文件bash # 加载Shell非登录环境sh/bash 脚本文件 |
---|
退出shell当前环境:
logout
:只能退出Shell登录环境。exit
:可以退出Shell登录与非登录环境查看系统环境变量:
env
:查看当前Shell系统环境变量。set
:查看Shell变量(系统环境变量+自定义变量+函数)。常用系统环境变量介绍:
变量名称 | 含义 |
---|---|
PATH | 与windows环境变量PATH功能一样,设置命令的搜索路径,以冒号为分割 |
HOME | 当前用户主目录:/root |
SHELL | 当前shell解析器类型:/bin/bash |
HISTFILE | 显示当前用户执行命令的历史列表文件:/root/.bash_history |
PWD | 显示当前所在路径:/root |
OLDPWD | 显示之前的路径 |
HOSTNAME | 显示当前主机名:itheima |
HOSTTYPE | 显示主机的架构,是i386、i686、还是x86、x64等:x86_64 |
LANG | 设置当前系统语言环境:zh_CN.UTF-8 |
自定义变量分为三种类型:
变量的定义:
1 | var_name=value |
---|
变量定义规则:
变量的取值:
12345 | # 语法1: 直接使用变量名查询$var_name# 语法2: 使用花括号${var_name}# 区别: 花括号方式适合拼接字符串 |
---|
注意: 如果echo "My name is
变量删除:
1 | unset var_name |
---|
设置自定义常量:
1 | readonly var_name |
---|
在定义好局部变量之后,执行readonly var_name
即可把变量设置为只读,之后不可再对该变量进行赋值操作。
设置自定义全局变量:
1 | export var_name1 var_name2 |
---|
全局变量可以在当前shell环境的子环境中也可以使用,例如,我们创建2个脚本文件:parent.sh
和child.sh
:
123456 | #!/bin/bash#parent.shvar_global=testexport var_globalecho "parent.sh中输出var_global变量:${var_global}"bash child.sh |
---|
123 | #!/bin/bash#child.shecho "child.sh中输出var_global变量:${var_global}" |
---|
然而直接在交互式Shell环境中打印${var_global}
是得不到结果的,说明全局变量在当前Shell环境与子Shell环境中可用,父Shell环境中不可用。
特殊变量 | 含义 |
---|---|
$n | 获取输入参数的$0, 获取当前Shell脚本文件名字$1~$9, 获取第一个输入参数到第九个输入参数${10} 获取10和10以上的参数需要使用花括号 |
$# | 获取所有输入参数的个数 |
$* 与 $@ | 获取所有输入参数数据区别: 如果不使用双引号, 功能一样, 获取所有参数数据为一个字符串, 如果使用了双引号, $@获取的就是参数列表对象, 每个参数都是一个独立字符串。 |
$? | 获取上一个命令的退出状态码, 一般;来说0代表命令成功,非0代表执行失败。 |
$$ | 获取当前shell环境进程的ID号。 |
$n
用于接收脚本文件执行时传入的参数:
1 | sh 脚本文件 输入参数1 输入参数2 ... |
---|
#获取所有输入参数的个数(脚本文件本身并不计算再内),也就是从1开始计数。
*和@都是获取所有输入参数, 用于以后输出所有参数。
区别:
演示:
直接输出所有输入参数, 与循环方式输出所有输入参数(使用双引号包含 * 与 @ ),创建test.sh:
1234567891011121314151617181920212223242526272829303132 | #!/bin/bash# 命令1: 打印当前脚本文件名字echo "当前脚本文件名称:$0"# 命令2: 打印第1个输入参数echo "第一个输入参数:$1"# 命令3: 打印第2个输入参数echo "第二个输入参数:$2"# 命令4: 打印第10个输入参数echo "第十个输入参数不带花括号获取:$10"echo "第十个输入参数带花括号获取:${10}"# 命令5 打印所有输入参数的个数echo "所有输入参数个数:${#}"# 增加命令: 实现直接输出所有输入后参数echo '使用$*直接输出:'$*echo '使用$@直接输出:'$@# 增加命令: 使用循环打印输出所有输入参数echo '循环遍历输出$*所有参数'for item in "$*"do echo $itemdoneecho '循环遍历输出$@所有参数'for item in "$@"do echo $itemdone |
---|
执行效果:
$?
用于获取上一个Shell命令的退出状态码, 或者是函数的返回值,每个Shell命令的执行都有一个返回值, 这个返回值用于说明命令执行是否成功,一般来说, 返回0代表命令执行成功, 非0代表执行失败。
$$用于获取当前Shell环境的进程ID号:
当前用户进入Shell环境初始化的时候会加载全局配置文件/etc/profile
里面的环境变量,供给所有Shell程序使用,以后只要是所有Shell程序或命令使用的变量就可以定义在这个文件中。
演示:
添加设置变量VAR1=VAR1并导出成为环境变量, 在系统级全局配置文件/etc/profile
末尾添加如下命令:
123 | # 创建环境变量VAR1=VAR1export VAR1 |
---|
保存/etc/profile
退出,重新加载/etc/profile
文件数据更新系统环境变量。(注意:如果这一步不执行,无法读取更新的环境变量)
1 | source /etc/profile |
---|
在交互式Shell中输出环境变量
1 | echo $VAR1 |
---|
字符串是 Shell 编程中最常用的数据类型之一,除了数字和字符串,也没有其他类型了,Shell的变量默认就是字符串。
字符串变量有3种格式表示,我们先设置一个变量var1=abc
,然后比较3种格式的效果:
单引号:任何字符都会原样输出,在其中使用变量是无效的。
123 | var2='abc${var1}'echo $var2#输出:abc${var1} |
---|
双引号(推荐):其中包含了变量,那么该变量会被解析得到值,而不是原样输出。如果字符串中还包含了双引号则需要转义。
1234567 | var2="abc${var1}"echo $var2#输出:abcabcvar3="hello,\"${var1}\""echo $var3#输出:hello,"abc" |
---|
不用引号:不被引号包围的字符串中出现变量时也会被解析,这一点和双引号" "
包围的字符串一样。但字符串中不能出现空格,否则空格后边的字符串会作为其他变量或者命令解析。
1234567 | var2=abc${var1}echo $var2#输出:abcabcvar2=abc ${var1}echo $var2#报错:-bash: abc: command not found |
---|
字符串拼接:
设置变量var=abc
变量取值:
1 | echo ${var} #输出:abc |
---|
获取字符串长度:
1 | echo ${#var} #输出:3 |
---|
截取语法:
格式 | 说明 |
---|---|
${变量名:start:length} | 从 string 字符串的左边第 start 个字符开始,向右截取 length 个字符。 |
${变量名:start} | 从 string 字符串的左边第 start 个字符开始截取,直到最后。 |
${变量名:0-start:length} | 从 string 字符串的右边第 start 个字符开始,向右截取 length 个字符。 |
${变量名:0-start} | 从 string 字符串的右边第 start 个字符开始截取,直到最后。 |
${变量名#*chars} | 从 string 字符串第一次出现*chars的位置开始,截取*chars右边的所有字符。 |
${变量名##*chars} | 从 string 字符串最后一次出现*chars的位置开始,截取*chars右边的所有字符。 |
${变量名%chars*} | 从 string 字符串最后一次出现chars*的位置开始,截取chars*左边的所有字符。 |
${变量名%%chars*} | 从 string 字符串第一次出现chars*的位置开始,截取chars*左边的所有字符。 |
示例,截取path
变量的值
操作 | 结果 |
---|---|
${path#/*:} | /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin |
${path##/*:} | /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin |
${path%:*bin} | /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin |
${path%%:*bin} | /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin |
替换语法:
格式 | 说明 | 示例 |
---|---|---|
${变量名/旧字符串/新字符串} | 将旧字符串替换成新字符串,仅替换第一个 | ${path/sbin/SBIN}将sbin替换成SBIN,仅替换第一个 |
${变量名//旧字符串/新字符串} | 将旧字符串替换成新字符串,替换所有 | ${path//sbin/SBIN}将sbin替换成SBIN,所有的都替换 |
变量的测试及默认值:
变量设定方式 | str没有设定 | str为空字符串 | str已设定非为空字符串 |
---|---|---|---|
var=${str-expr} | var=expr | var=$str=空 | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var=空 | var=expr | var=expr |
var=${str:+expr} | var=空 | var=空 | var=expr |
var=${str=expr} | str=exprvar=expr | str不变var=$str=空 | str不变var=$str |
var=${str:=expr} | str=exprvar=expr | str=exprvar=expr | str不变var=$str |
var=${str?expr} | expr输出至stderr | var=$str=空 | var=$str |
var=${str:?expr} | expr输出至stderr | expr输出至stderr | var=$str |
-
,=
,?
都是测试str
变量是否设定,如果str
没有设定则将表达式的值赋值给var
,有设定则赋值str
的值。区别就在于-
只会更新val
的值,而=
会同时更新str
,?
则只会将表达式的值输出到标准错误,并不会赋值给var
。
+
与上面的规则相反,它表示只有str
有设定值时才会将表达式的值赋值给var
,如果没有设定值,则var
赋值为空。
:
的意义在于,如果不加:
默认空字符串也表示str
有设定值,而加上:
则表示如果str
设定了值,但值为空字符串,依然当作str
没有设定值处理。
定义:
1234 | arr=(29 100 13 8 91 44)arr=(20 56 "abc")arr=([0]=1 [2]=100 [4]=aa) #可直接对索引赋值进行初始化,由于上面只赋值了3个元素, 所以数组的长度是3arr[6]=100 #Shell数组元素定义后不是固定的, 定义后还可以赋值 |
---|
获取:
1234 | ${arr[1]} #通过下标获取${arr[@]} #获取数组所有元素,也可以使用${arr[*]}${#arr[@]} #获取数组的长度或个数,也可以使用${#arr[*]}${#arr[1]} #获取数组索引1元素的字符长度 |
---|
拼接:
12 | array_new=(${array1[@]} ${array2[@]} ...)array_new=(${array1[*]} ${array2[*]} ...) |
---|
注:拼接后,新数组的索引为重新排列
删除:
12 | unset array_name[index] #删除数组指定元素数据unset array_name #删除整个数组 |
---|