2-shell变量

1 变量基础

1.1 变量场景

数据存储、变量场景

数据存储

所谓的数据存储,我们从三方面来理解这句话:
    1、数据保存到哪里	--	各种媒介,CPU、内存、磁盘、磁带、网盘...
    2、数据保存的效果	--	完整、安全、有效
    3、数据保存的单元	--	存储空间

	数据的存储空间默认不是一个整体,而是由一个个的存储单元组成,每一个存储单元都有一个唯一的整数编号,我们称这个编号为:地址
    存储单元的作用:存储数据+读写数据
    存储空间大小:1字节(B) = 8bit == 00000000
    地址特点:十六进制,例如:0x20000000

对于数据的存储来说,主要有两种样式:物理地址和逻辑地址。
    物理地址:内存或硬盘中真正存储数据的位置,也就是说通过磁盘设备查找的位置
    逻辑地址:用于查找物理地址的存储块地址叫逻辑地址。程序中用的地址一般都是逻辑地址
    逻辑地址包括两部分:起始值(十六进制)+偏移量(十六进制)
    数据表的描述主要是逻辑地址,因为程序一般存储的是逻辑地址。

数据一旦存储下来就不再发生变化了,而程序中可能会在很多场景中用到同一个数据,就会出现两个问题:
	1 物理地址人听得懂,机器看不懂 
		- 所以用逻辑地址找物理地址
	2 软件可以通过逻辑地址找到数据地址,但是软件不懂场景
		- 所以人用逻辑地址的别名来代指向同一个xx地址
		
应用程序中为了 多场景应用这个逻辑地址的别名,本质上就是“变量”。

变量场景

变量的本质

变量的本质其实就是 通过一个名称帮助程序快速找到内存中具体数据的地址。
	- 变量说白了就是指向xx值。

编程语言

编程语言在数据调用层面分类的话,可以分为两类:
	静态编译语言:
		使用变量前,先声明变量类型,之后类型不能改变,在编译时检查。
		如:java,c
	动态编译语言:
		不用事先声明,可随时改变类型。
		如:bash,Python

根据编程语言在使用变量的程度上,可以划分为强类型、弱类型语言:
    强类型语言:
    	不同类型数据操作,必须经过强制转换才同一类型才能运算。
    		如java , c# ,python
        示例:
            print('test' + 10) 提示出错,不会自动转换类型
            print('test' + str(10)) 结果为test10,需要显示转换类型
    弱类型语言:
    	语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;
    	参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用。
    	如:bash ,php,javascript
    	示例:
    		echo 'aaa'+222

1.2 变量定义

变量定义、变量分类

变量定义

变量包括三部分:
	变量名 - 不变的
	变量值 - 变化的
	赋值动作 - 变量名指向变量值
表现样式:
	变量名=变量值

	变量的全称应该成为变量赋值,简称变量,在工作中,我们一般只xx是变量,其实是是将这两者作为一个整体来描述了。准确来说,我们一般所说的变量其实指的是:变量名。

命名规范

1 名称有意义
2 名称细节
	命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
    中间不能有空格,可以使用下划线(_)。
    不能使用标点符号。
    不能使用bash里的关键字(可用help命令查看保留关键字)。
3 命名样式
	大驼峰HelloWorld,每个单词的首字母是大写
	小驼峰helloWorld,第一个单词的首字母小写,后续每个单词的首字母是大写
	下划线: Hello_World
	大小写字母: helloworld, HELLOWORLD

注意:
	对于开发人员来说,他们对于变量名的规范比较多,什么类、函数、对象、属性、命名空间等都有要求
	对于运维人员来说,记住一个词 -- 有意义。

变量分类

shell 中的变量分为三大类:
    本地变量		变量名仅仅在当前终端有效	
    全局变量		变量名在当前操作系统的所有终端都有效
    shell内置变量	shell解析器内部的一些功能参数变量

注意:
	这里的变量分类的特点仅仅是从字面上来理解的,因为在实际的操作的时候,还会涉及到环境优先级的问题
	所以生产中对于这三者的划分没有特别大的强制。

1.3 基本操作

变量查看、变量定义、变量移除

变量查看

语法解析

基本格式
	$变量名

示例

查看默认的shell类型
[root@localhost ~]# echo $SHELL
/bin/bash

变量定义

普通语法解析

基本格式
	变量名=变量值
	
注意:
	= 两侧不允许有空格

示例

查看一个空值变量名
[root@localhost ~]#  echo $myname

定制变量实践
[root@localhost ~]# myname=zhangsan
[root@localhost ~]#  echo $myname
zhangsan

错误的定制变量命令
[root@localhost ~]#  echo $myage

[root@localhost ~]# myage = 18
bash: myage: 未找到命令
[root@localhost ~]#  echo $myage

类型变量定义

命令语法
	declare 参数 变量名=变量值
参数解析:
    -i 将变量看成整数 
    -r 使变量只读  readonly,该变量的值无法改变,并且不能为unset
    -x 标记变量为全局变量,类似于export
    -a	指定为索引数组(普通数组)
    -A 指定为关联数组
注意:
	在生产场景中,这种方法比较鸡肋,使用频率很低

设定制定类型的变量值
[root@localhost ~]# declare -i mynum='zhangsan'
[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
zhangsan

移除变量名
[root@localhost ~]# unset myname
[root@localhost ~]#  echo $myname

[root@localhost ~]#

2 本地变量

2.1 本地变量分类

本地变量

所谓的本地变量就是:在当前系统的某个环境下才能生效的变量,作用范围小。

变量分类

本地变量按照变量值的生成方式包含两种:
	普通变量:
		自定义变量名和变量值
	命令变量:
		自定义变量名,而变量值是通过一条命令获取的

2.2 普通变量

基本格式

序号样式要点
方式一变量名=变量值变量值必须是一个整体,中间没有特殊字符
“=” 前后不能有空格
方式二变量名=‘变量值’原字符输出,我看到的内容,我就输出什么内容
方式三变量名=“变量值”如果变量值范围内,有可以解析的变量A,那么首先解析变量A,
将A的结果和其他内容组合成一个整体,重新赋值给变量B
习惯:
	数字不加引号,其他默认加双引号
	因为bash属于弱类型语言,默认会将所有内容当成字符串

变量定义

查看默认的空值变量
[root@localhost ~]# echo $name

方法1设定变量
[root@localhost ~]# name=zhangsan
[root@localhost ~]# echo $name
zhangsan

方法2设定变量
[root@localhost ~]# name='zhangsan'
[root@localhost ~]# echo $name
zhangsan

方法3设定变量
[root@localhost ~]# name="zhangsan"
[root@localhost ~]# echo $name
zhangsan

清理变量
[root@localhost ~]# unset name

作用区别演示

查看默认的空值变量
[root@localhost ~]# echo $name2

方法1设定变量的要点,变量值必须是一个整体
[root@localhost ~]# name2=zhangsan haoshuai
bash: haoshuai: 未找到命令
[root@localhost ~]# echo $name2
原因解析:
	空格是一个特殊符号,表示两条命令的隔开
	它将zhangsan 和 haoshuai当成两条命令了,所以报错信息是命令找不到
	
方法2设定变量
[root@localhost ~]# name2='zhangsan haoshuai'
[root@localhost ~]# echo $name2
zhangsan haoshuai

方法3设定变量
[root@localhost ~]# name2="zhangsan haoweiwu"
[root@localhost ~]# echo $name2
zhangsan haoweiwu	

清理变量
[root@localhost ~]# unset name2

定制基础变量
[root@localhost ~]# name=zhangsan
[root@localhost ~]# echo $name
zhangsan

方法2设定变量
[root@localhost ~]# name2='dan-$name'
[root@localhost ~]# echo $name2
dan-$name

方法3设定变量
[root@localhost ~]# name2="shuang-$name"
[root@localhost ~]# echo $name2
shuang-zhangsan

2.3 命令变量

基本格式

定义方式一:
	变量名=`命令`
    注意:
    ` 是反引号

定义方式二:
	变量名=$(命令)

执行流程:
	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
# 功能:获取当前主机的网卡设备信息
# 版本:V0.2

# 定制基础变量
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

文件执行后效果

在这里插入图片描述

3 全局变量

3.1 基本操作

基本定义

全局变量是什么
	全局变量就是:在当前系统的所有环境下都能生效的变量。

基本语法

查看全局环境变量
	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
...

查看制定的全局变量
[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

3.2 文件体系

变量文件

在linux环境中,有很多目录下的文件都可以定制一些作用范围更广的变量,这些文件或文件所在的目录有:
	作用范围在制定的用户范围:
        ~/.bashrc
        ~/.bash_profile
    作用的范围在系统范围:
        /etc/profile
        /etc/profile.d/env_file_name

简单实践

bashrc 或 bash_profile 实践

查看未知的变量名
[root@localhost ~]# echo $NAME

定制变量名到文件中
[root@localhost ~]# echo NAME=zhangsan >> ~/.bashrc
[root@localhost ~]# source ~/.bashrc
[root@localhost ~]# echo $NAME
zhangsan

新开一个终端查看效果
[root@localhost ~]# echo $NAME
zhangsan

新开一个普通用户的终端查看效果
[root@localhost ~]# su - python
[python@localhost ~]$ echo $NAME

[python@localhost ~]$

清理.bashrc 文件里的变量,然后清除当前环境下的变量名
unset NAME

profile实践

查看未知的变量名
[root@localhost ~]# echo $PROFILE

定制变量名到文件中
[root@localhost ~]# echo PROFILE=zhangsan >> /etc/profile
[root@localhost ~]# source /etc/profile
[root@localhost ~]# echo $PROFILE
zhangsan

新开一个终端查看效果
[root@localhost ~]# echo $PROFILE
zhangsan

新开一个普通用户的终端查看效果
[root@localhost ~]# su - python
[python@localhost ~]$ echo $PROFILE
zhangsan
[python@localhost ~]$

3.3 嵌套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='zhang'
_name="san"
_age="18"
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="lisi"
echo "子shell修改后的信息: $_xing"

执行测试效果
[root@localhost ~]# /bin/bash father.sh
父shell信息: zhangsan,18
子shell信息: zhangsan,18
子shell修改后的信息: lisi
父shell信息: lisisan,18

4 内置变量

4.1 脚本相关

脚本相关的变量解析

序号变量名解析
1$0获取当前执行的shell脚本文件名
2$n获取当前执行的shell脚本的第n个参数值,n=1…9,
当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

4.2 字符串相关

字符串相关的变量解析

字符串计数
	${#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	

4.3 默认值相关

语法解读

格式一:${变量名:-默认值}	
	变量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} 岁"

4.4 其他相关

脚本相关的变量解析

序号变量名解析
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
杀死当前的进程
[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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值