变量基础
变量查看
语法解析
基本格式
$变量名
示例
查看默认的shell类型
[root@localhost ~]# echo $SHELL
/bin/bash
4种查看变量的写法:
变量定义
普通语法解析
基本格式
变量名=变量值
注意:
= 两侧不允许有空格
示例
查看一个空值变量名
[root@localhost ~]# echo $myname
定制变量实践
[root@localhost ~]# myname=shuji
[root@localhost ~]# echo $myname
shuji
错误的定制变量命令
[root@localhost ~]# echo $myage
[root@localhost ~]# myage = 18
bash: myage: 未找到命令
[root@localhost ~]# echo $myage
类型变量定义
命令语法
declare 参数 变量名=变量值
参数解析:
-i 将变量看成整数
-r 使变量只读 readonly,==**该变量的值无法改变,并且不能为unset**==
-x 标记变量为全局变量,类似于export
-a 指定为索引数组(普通数组);查看普通数组
-A 指定为关联数组;查看关联数组
注意:
在生产场景中,这种方法比较鸡肋,使用频率 0-20次/3年
设定制定类型的变量值
[root@localhost ~]# declare -i mynum='shuzi'
[root@localhost ~]# echo $mynum
0
[root@localhost ~]# declare -i mynum='123456'
[root@localhost ~]# echo $mynum
123456
设定只读类型变量
[root@localhost ~]# declare -r myread1="aaa"
[root@localhost ~]# myread2=myread
[root@localhost ~]# readonly myread2
查看只读变量
[root@localhost ~]# declare -r | grep myread
declare -r myread1="aaa"
declare -r myread2="myread"
[root@localhost ~]# readonly -p | grep myread
declare -r myread1="aaa"
declare -r myread2="myread"
无法使用unset删除只读变量
[root@localhost ~]# unset myread1 myread2
bash: unset: myread1: 无法反设定: 只读 variable
bash: unset: myread2: 无法反设定: 只读 variable
借助于exit方式删除只读变量
[root@localhost ~]# exit
...... 重新登录后再次查看
[root@localhost ~]# declare -r | grep myread
[root@localhost ~]#
查看只读变量示例:
也可以使用管道然后过滤
删除只读变量示例:
先退出终端
重新连接就没了
变量移除
语法解析
基本格式
unset 变量名
示例
查看刚才定制的变量名
[root@localhost ~]# echo $myname
shuji
移除变量名
[root@localhost ~]# unset myname
[root@localhost ~]# echo $myname
[root@localhost ~]#
本地变量
普通变量
变量分类
所谓的本地变量就是:在当前系统的某个环境下才能生效的变量,作用范围小。本地变量按照变量值的生成方式包含两种:
普通变量:
自定义变量名和变量值
命令变量:
自定义变量名,而变量值是通过一条命令获取的
基本格式
序号 | 样式 | 要点 |
---|---|---|
方式一 | 变量名=变量值 | 变量值必须是一个整体,中间没有特殊字符 "=" 前后不能有空格 |
方式二 | 变量名='变量值' | 原字符输出,我看到的内容,我就输出什么内容, |
方式三 | 变量名="变量值" | 如果变量值范围内,有可以解析的变量A,那么首先解析变量A, 将A的结果和其他内容组合成一个整体,重新赋值给变量 |
习惯:
数字不加引号,其他默认加双引号
因为bash属于弱类型语言,默认会将所有内容当成字符串
变量定义
查看默认的空值变量
[root@localhost ~]# echo $name
方法1设定变量
[root@localhost ~]# name=shuji
[root@localhost ~]# echo $name
shuji
方法2设定变量
[root@localhost ~]# name='shuji1'
[root@localhost ~]# echo $name
shuji1
方法3设定变量
[root@localhost ~]# name="shuji2"
[root@localhost ~]# echo $name
shuji2
清理变量
[root@localhost ~]# unset name
作用区别演示
查看默认的空值变量
[root@localhost ~]# echo $name2
方法1设定变量的要点,变量值必须是一个整体
[root@localhost ~]# name2=shuji haoshuai
bash: haoshuai: 未找到命令
[root@localhost ~]# echo $name2
原因解析:
空格是一个特殊符号,表示两条命令的隔开
它将shuji 和 haoshuai当成两条命令了,所以报错信息是命令找不到
方法2设定变量
[root@localhost ~]# name2='shuji haoshuai'
[root@localhost ~]# echo $name2
shuji haoshuai
方法3设定变量
[root@localhost ~]# name2="shuji haoweiwu"
[root@localhost ~]# echo $name2
haoweiwu
清理变量
[root@localhost ~]# unset name2
定制基础变量
[root@localhost ~]# name=shuji
[root@localhost ~]# echo $name
shuji
方法2设定变量
[root@localhost ~]# name2='dan-$name'
[root@localhost ~]# echo $name2
dan-$name
方法3设定变量
[root@localhost ~]# name2="shuang-$name"
[root@localhost ~]# echo $name2
shuang-shuji
命令变量
基本格式
定义方式一:
变量名=`命令`
注意:
` 是反引号
定义方式二:推荐使用
变量名=$(命令)
执行流程:
1、执行 ` 或者 $() 范围内的命令
2、将命令执行后的结果,赋值给新的变量名A
简单实践
命令变量实践
查看默认的空值变量
[root@localhost ~]# echo $myuser
方法1设定变量名
[root@localhost ~]# myuser=`whoami`
[root@localhost ~]# echo $myuser
root
查看默认的空值变量
[root@localhost ~]# echo $mydir
方法2设定变量名
[root@localhost ~]# mydir=$(pwd)
[root@localhost ~]# echo $mydir
/root
清理变量
[root@localhost ~]# unset mydir myuser
其他常见的实践
自动生成一系列数字
[root@localhost ~]# NUM=`seq 10`
[root@localhost ~]# echo $NUM
1 2 3 4 5 6 7 8 9 10
文件备份添加时间戳
[root@localhost ~]# touch file-a
[root@localhost ~]# cp file-a file-a-$(date +%F)
[root@localhost ~]# ls file-a*
file-a file-a-2022-06-08
简单小综合实践
[root@localhost ~]# cat get_netinfo_v2.sh
#!/bin/bash
# 功能:获取当前主机的网卡设备信息
# 作者:wangshuji
# 版本:V0.2
# 联系:www.superopsmsb.com
# 定制基础变量
RED="\E[1;31m"
GREEN="echo -e \E[1;32m"
END="\E[0m"
# 获取ip地址信息
IPDDR=$(ifconfig eth0 | grep -w inet | awk '{print $2}')
# 获取掩码地址信息
NETMAST=$(ifconfig eth0 | grep -w inet | awk '{print $4}')
# 获取广播地址信息
BROADCAST=$(ifconfig eth0 | grep -w inet | awk '{print $6}')
# 获取MAC地址信息
MACADDR=$(ifconfig eth0 | grep ether | awk '{print $2}')
# 打印网络基本信息
$GREEN---------主机网卡基本信息---------$END
echo -e "HOSTNAME: $RED `hostname` $END"
echo -e "IP: $RED $IPDDR $END"
echo -e "NetMask: $RED $NETMAST $END"
echo -e "Broadcast: $RED $BROADCAST $END"
echo -e "MAC Address: $RED $MACADDR $END"
$GREEN---------主机网卡基本信息---------$END
全局变量
基本定义
全局变量是什么
全局变量就是:在当前系统的所有环境下都能生效的变量。
基本语法
查看全局环境变量
env 只显示全局变量,一般结合 grep 和管道符来使用
printenv 效果与env等同
export 查看所有的环境变量,包括声明的过程等信息,一般不用
declare -x 效果与export类似
定义全局变量方法一:
变量=值
export 变量
定义全局变量方法二:(最常用)
export 变量=值
简单实践
查看所有的全局变量
[root@localhost ~]# env
XDG_SESSION_ID=4
HOSTNAME=localhost
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
...
查看制定的全局变量,grep筛选
[root@localhost ~]# env | grep SHELL
SHELL=/bin/bash
定制本地变量
[root@localhost ~]# envtype=local
[root@localhost ~]# echo $envtype
local
从全局变量中查看
[root@localhost ~]# env | grep envtype
[root@localhost ~]#
结果显示:
无法从全局变量中查看本地变量的名称
方法1定制全局变量
[root@localhost ~]# echo $envtype
local
[root@localhost ~]# env | grep envtype
[root@localhost ~]# export envtype
[root@localhost ~]# env | grep envtype
envtype=local
方法2定制全局变量
[root@localhost ~]# export myuser=root
[root@localhost ~]# env | grep myuser
myuser=root
鸡肋方法定制全局变量,别用,不好
[root@localhost ~]# declare -x mydir=/root
[root@localhost ~]# env | grep mydir
mydir=/root
清理全局变量
[root@localhost ~]# unset envtype myuser mydir
文件体系
变量文件
变量文件
在linux环境中,有很多目录下的文件都可以定制一些作用范围更广的变量,这些文件或文件所在的目录有:
作用范围在制定的用户范围:
~/.bashrc
~/.bash_profile
作用的范围在系统范围:
/etc/profile
/etc/profile.d/env_file_name
简单实践
bashrc 或 bash_profile 实践
查看未知的变量名
[root@localhost ~]# echo $NAME
定制变量名到文件中
[root@localhost ~]# echo NAME=shuji >> ~/.bashrc
[root@localhost ~]# source ~/.bashrc
[root@localhost ~]# echo $NAME
shuji
新开一个终端查看效果
[root@localhost ~]# echo $NAME
shuji
新开一个普通用户的终端查看效果
[root@localhost ~]# su - python
[python@localhost ~]$ echo $NAME
[python@localhost ~]$
清理.bashrc 文件里的变量,然后清除当前环境下的变量名
unset NAME
新开一个普通用户的终端查看效果
profile实践
系统下的所有用户都能查到变量
查看未知的变量名
[root@localhost ~]# echo $PROFILE
定制变量名到文件中
[root@localhost ~]# echo PROFILE=shuji >> /etc/profile
[root@localhost ~]# source /etc/profile
[root@localhost ~]# echo $PROFILE
shuji
新开一个终端查看效果
[root@localhost ~]# echo $PROFILE
shuji
新开一个普通用户的终端查看效果
[root@localhost ~]# su - python
[python@localhost ~]$ echo $PROFILE
shuji
[python@localhost ~]$
嵌套shell
export原理
原理解析
用户登录时:
用户登录到Linux系统后,系统将启动一个用户shell。
在这个shell中,可以使用shell命令或声明变量,也可以创建并运行 shell脚本程序。
运行脚本时:
运行shell脚本程序时,系统将创建一个子shell。 此时,系统中将有两个shell
- 一个是登录时系统启动的shell,另一个是系统为运行脚本程序创建的shell。
当一个脚本程序运行完毕,它的脚本shell将终止,可以返回到执行该脚本之前的shell。
意义解读
从这种意义上来说,用户可以有许多 shell,每个shell都是由某个shell(称为父shell)派生的。
在子shell中定义的变量只在该子shell内有效。如果在一个shell脚本程序中定义了一个变量,当该脚本程序运行时,这个定义的变量只是该脚本程序内的一个局部变量,其他的shell不能引用它,要使某个变量的值可以在其他shell中被改变,可以使用export命令对已定义的变量进行输出。
export命令将使系统在创建每一个新的shell时定义这个变量的一个拷贝。这个过程称之为变量输出。
实践解读
当前父shell中定义变量中,分为局部变量和全局变量,不同点是:
- 局部变量只能作用于本父shell,子shell无法继续使用
- 如果使用了export将局部变量定义为全局变量,那么子shell创建的时候会继承父shell的全局变量
嵌套实践
简单实践
查看父shell的脚本
[root@localhost ~]# cat father.sh
#!/bin/bash
# 定制全局变量
export _xing='王'
_name="书记"
_age="42"
echo "父shell信息: $_xing$_name,$_age"
sleep 3
# 调用child.sh进行验证,最好放在同一目录下
/bin/bash child.sh
echo "父shell信息: $_xing$_name,$_age"
查看子shell的脚本
#!/bin/bash
# 显示父shell的全局变量
echo "子shell信息: $_xing$_name,$_age"
# 同名变量 子shell 的优先级高于父shell,但是不会传递给父shell
_xing="王胖胖"
echo "子shell修改后的信息: $_xing"
执行测试效果
[root@localhost ~]# /bin/bash father.sh
父shell信息: 王书记,42
子shell信息: 王,
子shell修改后的信息: 王胖胖
父shell信息: 王书记,42
执行脚本
验证子脚本的同名变量是否会覆盖父脚本
验证子脚本修改变量后,父脚本是否受影响
内置变量
脚本相关
基础知识
脚本相关的变量解析
序号 | 变量名 | 解析 |
---|---|---|
1 | $0 | 获取当前执行的shell脚本文件名 |
2 | \(n | 获取当前执行的shell脚本的第n个参数值,n=1..9,<br />当n为0时表示脚本的文件名,如果n大于9就要用大括号括起来\){10} | |
3 | $# | 获取当前shell命令行中参数的总个数 |
4 | $? | 获取执行上一个指令的返回值(0为成功,非0为失败) |
简单实践
实践1 - $0 获取脚本的名称
[root@localhost ~]# cat get_name.sh
#!/bin/bash
# 获取脚本的名称
echo "我脚本的名称是: file.sh"
echo "我脚本的名称是:$0"
实践2 - $n 获取当前脚本传入的第n个位置的参数
[root@localhost ~]# cat get_args.sh
#!/bin/bash
# 获取指定位置的参数
echo "第一个位置的参数是: $1"
echo "第二个位置的参数是: $2"
echo "第三个位置的参数是: $3"
echo "第四个位置的参数是: $4"
实践3 - $# 获取当前脚本传入参数的数量
[root@localhost ~]# cat get_number.sh
#!/bin/bash
# 获取当前脚本传入的参数数量
echo "当前脚本传入的参数数量是: $#"
实践4 - $? 获取文件执行或者命令执行的返回状态值
[root@localhost ~]# bash nihao
bash: nihao: No such file or directory
[root@localhost ~]# echo $?
127
[root@localhost ~]# ls
get_name.sh get_args.sh get_number.sh
[root@localhost ~]# echo $?
0
字符串相关
基础知识
字符串相关的变量解析
字符串计数
${#file} 获取字符串的长度
字符串截取
- 语法为${var:pos:length} 表示对变量var从pos开始截取length个字符,pos为空表示0
${file:0:5} 从0开始,截取5个字符
${file:5:5} 从5开始,截取5个字符
${file::5} 从0开始,截取5个字符
${file:0-6:3} 从倒数第6个字符开始,截取之后的3个字符
${file: -4} 返回字符串最后四个字节,-前面是"空格"
简单实践
字符串实践
定制字符串内容
[root@localhost ~]# string_context="dsjfdsafjkldjsklfajkdsa"
[root@localhost ~]# echo $string_context
dsjfdsafjkldjsklfajkdsa
获取字符串长度
[root@localhost ~]# echo ${#string_context}
23
从0开始,截取5个字符
[root@localhost ~]# echo ${string_context:0:5}
dsjfd
从5开始,截取5个字符
[root@localhost ~]# echo ${string_context:5:5}
safjk
从0开始,截取5个字符
[root@localhost ~]# echo ${string_context::5}
dsjfd
从倒数第6个字符开始,截取之后的3个字符
[root@localhost ~]# echo ${string_context:0-6:3}
ajk
返回字符串最后四个字节,-前面是"空格"
[root@localhost ~]# echo ${string_context: -4}
kdsa
默认值相关
基础知识
语法解读
格式一:${变量名:-默认值}
变量a如果有内容,那么就输出a的变量值
变量a如果没有内容,那么就输出默认的内容
格式二:${变量名+默认值}
无论变量a是否有内容,都输出默认值
实践1 - 有条件的默认值
购买手机的时候选择套餐:
如果我输入的参数为空,那么输出内容是 "您选择的套餐是: 套餐 1"
如果我输入的参数为n,那么输出内容是 "您选择的套餐是: 套餐 n"
[root@localhost ~]# select_default_value.sh
#!/bin/bash
# 套餐选择演示
a="$1"
echo "您选择的手机套餐是: 套餐 ${a:-1}"
实践2 - 强制默认值
国家法律强制规定:
不管我说国家法定结婚年龄是 多少岁,都输出 国家法定结婚年龄(男性)是 22 岁
[root@localhost ~]# froce_default_value.sh
#!/bin/bash
# 默认值演示示例二
a="$1"
echo "国家法定结婚年龄(男性)是 ${a+22} 岁"
其他相关
基础知识
脚本相关的变量解析
序号 | 变量名 | 解析 |
---|---|---|
1 | $_ | 在此之前执行的命令或脚本的第一个内容 |
2 | $@ | 传给脚本的所有参数 |
3 | $* | 是以一个单字符串显示里所有向脚本传递的参数,与位置参数不同,参数可超过9个 |
4 | $$ | 是脚本运行的当前进程的ID号,作用是方便以后管理它杀掉他 |
5 | $! | 前一条命令进程的ID号,作用是方便以后管理它杀掉他 |
简单实践
实践1 - 其他变量的作用
[root@localhost ~]# cat get_other.sh
#!/bin/sh
echo "脚本执行命令的第一个内容: $_"
echo "传递给当前脚本的所有参数是: $@"
echo "单字符串显示所有参数: $*"
echo "当前脚本执行时候的进程号是: $$"
sleep 5 &
echo "上一条命令执行时候的进程号是: $!"
实践2 - $$ 获取当前的进程号
查看当前的进程号
[root@localhost ~]# echo $$
4759
[root@localhost ~]# ps aux | grep 4759
root 4759 0.0 0.0 116712 3356 pts/1 Ss 00:11 0:00 -bash
root 5547 0.0 0.0 112828 984 pts/1 S+ 02:00 0:00 grep --color=auto 4759
杀死当前的进程,等于正在使用的bash被杀死了
[root@localhost ~]# kill -9 4759
───────────────────────────────────────────
Session stopped
- Press <return> to exit tab
- Press R to restart session
- Press S to save terminal output to file
实践3 - $@ 和 $* 的区别
定制father脚本
[root@localhost ~]# cat father.sh
#!/bin/bash
echo "$0: 所有的参数 $@"
echo "$0: 所有的参数 $*"
echo '将 $* 值传递给 child-1.sh 文件'
/bin/bash child-1.sh "$*"
echo '将 $@ 值传递给 child-2.sh 文件'
/bin/bash child-2.sh "$@"
定制两个child脚本
[root@localhost ~]# cat child-1.sh
#!/bin/bash
echo "$0: 获取所有的参数 $1"
[root@localhost ~]# cat child-2.sh
#!/bin/bash
echo "$0: 获取所有的参数 $1"
执行 father.sh 脚本
[root@localhost ~]# /bin/bash father.sh 1 2 3
father.sh: 所有的参数 1 2 3
father.sh: 所有的参数 1 2 3
将 $* 值传递给 child-1.sh 文件
child-1.sh: 获取所有的参数 1 2 3
将 $@ 值传递给 child-2.sh 文件
child-2.sh: 获取所有的参数 1
验证结果: