Linux Shell基础篇二 - 变量
Shell变量
在Shell中包括有三种变量类型:系统环境变量、自定义变量和特殊符号变量。
系统环境变量
系统环境变量是系统提供的共享变量,是linux系统加载Shell的配置文件中定义的变量共享给所有的Shell程序使用。环境变量按照其作用范围不同大致可以分为系统级环境变量和用户级环境变量。
- 系统级环境变量:Shell环境加载全局配置文件中的变量共享给所有用户所有Shell程序使用,全局共享
- 用户级环境变量:Shell环境加载个人配置文件中的变量共享给当前用户的Shell程序使用,登录用户使用
Shell的配置文件分类:
全局配置文件
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc个人配置文件
当前用户/.bash_profile
当前用户/.bashrc
环境变量加载初始化过程:
- 登录Shell环境:需要用户名\密码登录的Shell环境,配置在:
/etc/profile
、/当前用户/.bash_profile
- 非登录Shell环境:不需要用户名,密码进入的Shell环境或执行脚本文件,配置在:
/当前用户/.bashrc
、/etc/bashrc
加载顺序:
查看当前Shell环境:
1 |
|
输出-bash
表示shell登录环境,输出bash
表示shell非登录环境。注意:这个 $0
环境变量如果用在子shell中(shell脚本文件)输出Shell脚本本身的文件名。
切换shell环境:
直接切换用户
1 |
|
切换Shell环境执行脚本文件
1 |
|
退出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 |
自定义变量
自定义变量分为三种类型:
- 自定义局部变量:就是定义在一个脚本文件中的变量, 只能在这个脚本文件中使用的变量, 就是局部变量
- 自定义常量:就是变量设置值以后不可以修改的变量叫常量, 也叫只读变量
- 自定义全局变量:就是在当前脚本文件中定义全局变量,这个全局变量可以在当前Shell环境与子Shell环境中都可以使用
变量的定义:
1 |
|
变量定义规则:
- 变量名称可以有字母,数字和下划线组成, 但是不能以数字开头
- 等号两侧不能有空格
- 在bash环境中, 变量的默认类型都是字符串类型, 无法直接进行数值运算
- 变量的值如果有空格, 必须使用双引号括起来
- 不能使用Shell的关键字作为变量名称
变量的取值:
1 |
|
注意: 如果echo "My name is ${var2}Style"
中 $var2
不带花括号,系统会认为获取$var2Style
变量数据,这个变量不存在就获取不到数据,所以尽量使用花括号获取变量值。
变量删除:
1 |
|
设置自定义常量:
1 |
|
在定义好局部变量之后,执行readonly var_name
即可把变量设置为只读,之后不可再对该变量进行赋值操作。
设置自定义全局变量:
1 |
|
全局变量可以在当前shell环境的子环境中也可以使用,例如,我们创建2个脚本文件:parent.sh
和child.sh
:
1 |
|
1 |
|
然而直接在交互式Shell环境中打印${var_global}
是得不到结果的,说明全局变量在当前Shell环境与子Shell环境中可用,父Shell环境中不可用。
特殊符号变量
特殊变量 | 含义 |
---|---|
$n |
获取输入参数的$0 , 获取当前Shell脚本文件名字$1~$9 , 获取第一个输入参数到第九个输入参数${10} 获取10和10以上的参数需要使用花括号 |
$# |
获取所有输入参数的个数 |
$* 与 $@ |
获取所有输入参数数据 区别: 如果不使用双引号, 功能一样, 获取所有参数数据为一个字符串, 如果使用了双引号, $@ 获取的就是参数列表对象, 每个参数都是一个独立字符串。 |
$? |
获取上一个命令的退出状态码, 一般;来说0代表命令成功,非0代表执行失败。 |
$$ | 获取当前shell环境进程的ID号。 |
$n
用于接收脚本文件执行时传入的参数:
1 |
|
- $0 用于获取当前脚本文件名称的
- $1~$9, 代表获取第一输入参数到第9个输入参数
- 第10个以上的输入参数获取参数的格式: ${数字},否则无法获取
$#
获取所有输入参数的个数(脚本文件本身并不计算再内),也就是从$1开始计数。
$*
和$@
都是获取所有输入参数, 用于以后输出所有参数。
区别:
- 不使用双引号括起来, 功能一样
$*
和$@
获取所有输入参数,格式为: $1 $2 … $n - 使用双引号括起来
“$*
“获取的所有参数拼接为一个字符串, 格式为: “$1 $2 … $n”
“$@
“获取一组参数列表对象, 格式为: “$1” “$2” … “$n”
使用循环打印所有输入参数可以看出区别
演示:
直接输出所有输入参数, 与循环方式输出所有输入参数(使用双引号包含 $*
与 $@
),创建test.sh
:
1 |
|
执行效果:
$?
用于获取上一个Shell命令的退出状态码, 或者是函数的返回值,每个Shell命令的执行都有一个返回值, 这个返回值用于说明命令执行是否成功,一般来说, 返回0代表命令执行成功, 非0代表执行失败。
$$用于获取当前Shell环境的进程ID号:
自定义系统环境变量
当前用户进入Shell环境初始化的时候会加载全局配置文件/etc/profile
里面的环境变量,供给所有Shell程序使用,以后只要是所有Shell程序或命令使用的变量就可以定义在这个文件中。
演示:
添加设置变量VAR1=VAR1并导出成为环境变量, 在系统级全局配置文件
/etc/profile
末尾添加如下命令:1
2
3# 创建环境变量
VAR1=VAR1
export VAR1保存
/etc/profile
退出,重新加载/etc/profile
文件数据更新系统环境变量。(注意:如果这一步不执行,无法读取更新的环境变量)1
source /etc/profile
在交互式Shell中输出环境变量
1
echo $VAR1
Shell字符串变量
字符串是 Shell 编程中最常用的数据类型之一,除了数字和字符串,也没有其他类型了,Shell的变量默认就是字符串。
变量的赋值
字符串变量有3种格式表示,我们先设置一个变量var1=abc
,然后比较3种格式的效果:
单引号:任何字符都会原样输出,在其中使用变量是无效的。
1
2
3var2='abc${var1}'
echo $var2
#输出:abc${var1}双引号(推荐):其中包含了变量,那么该变量会被解析得到值,而不是原样输出。如果字符串中还包含了双引号则需要转义。
1
2
3
4
5
6
7var2="abc${var1}"
echo $var2
#输出:abcabc
var3="hello,\"${var1}\""
echo $var3
#输出:hello,"abc"不用引号:不被引号包围的字符串中出现变量时也会被解析,这一点和双引号
" "
包围的字符串一样。但字符串中不能出现空格,否则空格后边的字符串会作为其他变量或者命令解析。1
2
3
4
5
6
7var2=abc${var1}
echo $var2
#输出:abcabc
var2=abc ${var1}
echo $var2
#报错:-bash: abc: command not found
字符串拼接:
- 无符号拼接:
echo ${var1}${var2}
- 双引号拼接:
echo "${var1}${var2}"
- 混合拼接:
echo ${var1}"&"${var2}"
或者echo ${var1}'&'${var2}
变量的取值
设置变量var=abc
变量取值:
1 |
|
获取字符串长度:
1 |
|
截取语法:
格式 | 说明 |
---|---|
${变量名: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#/*:} |
|
${path##/*:} |
|
${path%:*bin} |
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin |
${path%%:*bin} |
/usr/kerberos/sbin |
替换语法:
格式 | 说明 | 示例 |
---|---|---|
${变量名/旧字符串/新字符串} |
将旧字符串替换成新字符串,仅替换第一个 | ${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=expr var=expr |
str不变 var=$str=空 |
str不变 var=$str |
var=${str:=expr} |
str=expr var=expr |
str=expr var=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
没有设定值处理。
Shell索引数组变量
定义:
1
2
3
4arr=(29 100 13 8 91 44)
arr=(20 56 "abc")
arr=([0]=1 [2]=100 [4]=aa) #可直接对索引赋值进行初始化,由于上面只赋值了3个元素, 所以数组的长度是3
arr[6]=100 #Shell数组元素定义后不是固定的, 定义后还可以赋值获取:
1
2
3
4${arr[1]} #通过下标获取
${arr[@]} #获取数组所有元素,也可以使用${arr[*]}
${#arr[@]} #获取数组的长度或个数,也可以使用${#arr[*]}
${#arr[1]} #获取数组索引1元素的字符长度拼接:
1
2array_new=(${array1[@]} ${array2[@]} ...)
array_new=(${array1[*]} ${array2[*]} ...)注:拼接后,新数组的索引为重新排列
删除:
1
2unset array_name[index] #删除数组指定元素数据
unset array_name #删除整个数组