shell编程之变量定义
Posted 锦衣admin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell编程之变量定义相关的知识,希望对你有一定的参考价值。
变量介绍
计算机中的单位:
1B = 8b
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
1EB = 1024TB
b:是计算机内部数据储存的最基本单位(bit 位)
B:计算机中数据处理的基本单位,计算机中以字节为单位存储和解释信息(byte 字节)
cpu读取数据时的操作:
-
读:计算机将数据从硬盘读出存入内存,再从内存读出给CPU
-
写:CPU将数据存入内存,内存再将数据存入硬盘
变量介绍:
在编程中,我们总有一些数据需要存放在内存中,以待后续使用时快速读取。变量是编程中最常用的一种临时在内存中存取数据的一种方式
变量相当于一个容器,用于存放数据,变量有两个地址:
逻辑地址:变量的名称(PATH)
物理地址:内存中的块地址(0x05),数据存放的地方
变量的作用:临时在内存中存取数据,提升计算机的执行效率
变量存取原理:
关于内存的说明:
系统启动 => 内存被按照1B一个单位划分成N块,并且以十六进制为每一个块空间编号
内存跟踪表 => 使用和未使用内存空间的地址编号
内存申请 => 系统从未使用的内存中拿出一块或者一段连续的空间给用户使用,同时在内存跟踪表中
记录该地址被占用,不再分给别的用户使用,同时在系统中建立映射关系、
如变量名:STRING1 < == > 0x5(ABC)
释放内存 => 从跟踪表中删除映射记录,下次存数据直接覆盖原块空间
变量定义
什么时候需要定义变量?
-
如果某个内容需要多次使用,并且在代码中重复出现,那么就可以用变量代替该内容。这样在修改内容的时候,仅仅需要修改变量的值
-
在代码运作过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量
定义一个变量:
变量格式:变量名=变量值
在shel编程中,变量名和等号之间不能有空格
变量命名规则:
变量命名规则:
命名只能使用英文字母、数字和下划线,首字母不能数字开头
中间不能有空格,可以使用下划线。如:_name='abc'
不能使用标点符号
不能使用bash里的关键字(可用"help"命令查看保留关键字)
#l 注意:字符串要用单引号或双引号引起来;建议变量名为大写,和命令区分
变量的定义与取消:
"定义变量":变量赋值,此种方法设置本地变量
# xjj='hello' => 定义一个变量命令为xjj,值为hello的本地变量
[root@server ~]# xjj='hello'
[root@server ~]# echo $xjj => 需要$符号取变量值内容
hello
备注:定义变量会占用内存空间,除非重启系统释放内存或"unset"取消变量,否则这个变量会一直占用内存的空间
就算你关闭当前定义变量的这个shell,这个变量占用的内存空间也不会释放,删除的只是内存跟踪表的映射记录,
但是内存数据没有删除,还是会占用内存空间,这时候想使用这个内存空间除非是重新覆盖变量的值或者是unset取消变量
"取消变量":取消当前环境中的变量(释放内存),如果变量保存在文件中,下次重启又会恢复
# unset xjj => 通过"unset"命令取消当前环境的变量
[root@server ~]# echo $xjj
hello
[root@server ~]# unset xjj
[root@server ~]# echo $xjj => 变量没有了
变量类型:delcare命令
变量类型:
命令格式:
# declare [选项] 变量=值
选项说明:
-i:将变量类型限定为整数
-r:使变量只读readnoly,该变量的值无法改变,并且不能"unset"取消变量
-x:标记变量通过环境导出,export(即环境变量)
-a:指定索引数组(普通数组);查看普通数组
-A:指定为关联数组;查看关联数组
演示:
# declare -i age => -i 选项限定变量的类型为整数
[root@server ~]# age=13
[root@server ~]# echo $age
13
[root@server ~]# declare -i age
[root@server ~]# age=13.5 => 不能修改为浮点数类型
-bash: 13.5: syntax error: invalid arithmetic operator (error token is ".5")
[root@server ~]# age=11 => 可以修改为其他整数
[root@server ~]# echo $age
11
# declare -r Pi=3.14 => -r 选项限定变量的值
[root@server ~]# declare -r Pi=3.14
[root@server ~]# Pi=123
-bash: Pi: readonly variable
[root@server ~]# unset Pi => 无法取消变量
-bash: unset: Pi: cannot unset: readonly variable
变量分类
系统中的变量根据作用域及生命周期可以分为四类:本地变量、环境变量、全局变量、内置变量
本地变量
当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。定义在脚本或者当前终端中,脚本执行完毕或当前终端结束(窗口关闭)变量失效。
本地变量特点:
-
作用域:只作用于当前shell
-
生命周期:当前shell结束,本地变量失效
-
应用场景:临时变量
环境变量
定义在用户家目录下的.bashrc
或.bash_profile
文件中,用户私有变量,只能本用户使用。当前进程有效,并且能够被子进程调用。
- 查看当前用户的环境变量:
env命令
- 查询当前用户的所有变量(临时变量与环境变量):
set命令
- 将当前变量变成环境变量:
export命令
(,)
环境变量特点:
-
作用域:父shell及其子shell
-
生命周期:注销用户或者关机
-
应用场景:用户私有变量
-
永久定义(将一个本地变量变成环境变量):
~/.bash_profile
和~/.bashrc
文件(用户登录成功后这两个文件被加载)
将临时变量变成环境变量:
创建临时变量:
# age=100
[admin@server ~]$ age=100
[admin@server ~]$ echo $age
100
[admin@server ~]$ env | egrep 'age=100' => 环境变量中不存在此age变量
[admin@server ~]$ set | egrep 'age=100' => age变量存在临时变量中
age=100
加入环境变量:
# export age
[admin@server ~]$ export age => 临时将一个本地变量(临时变量)加入环境变量
[admin@server ~]$ env | egrep 'age=100' => 加入成功,环境变量中可以找到age变量
age=100
定义一个永久生效的本地变量:只能本用户使用
基于.bash_profile 文件定义:
# vim ~/.bash_profile => 定义
age=100
# source ~/.bash_profile => 引用文件
基于.bashrc 文件定义
#vim ~/.bashrc => 定义
age=100
# source ~/.bashrc => 引用文件
export 命令说明:
export
命令只是临时将本地变量变成环境变量,当前父shell结束则收回变量export
命令的作用域是当前shell及其子shell
需要注意:
- export命令变量输出(临时变量变成环境变量)是在当前shell中创建的,所以这个环境变量是在当前shell的环境变量里,不作用与当前shell同级的shell中。如:终端1变量输出一个临时变量,终端2不能调用
那为系统中的环境变量可以在各个终端下使用?
- 这是因为
~/.bash_profile
和~/.bashrc
文件在用户登录时被加载了,它的作用域是当前用户父shell的其他所有子shell
export命令说明:
用户登录时:
用户登录到Linux系统后,系统将启动一个用户shell。在这个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中定义变量分为局部变量和全局变量,不同点是局部变量只能作用于本父shell,子shell无法继续使用,如果使用export
命令将局部变量定义为全局变量,那么父shell在创建子shell的时候会将该变量一同复制给子shell环境
export命令变量输出说明:
在1.sh脚本中定义一个变量输出,在2.sh脚本中验证是否成功:
# vim 1.sh
#!/bin/bash
export _name='xjj' => 父shell定义一个全局变量
_Pi='yuan' => 定义一个本地变量
sleep 3 => 等待3秒
sh 2.sh => 执行2.sh
# vim 2.sh
#!/bin/bash
echo "name:$_name" => 输出当前shell的_name变量
echo "_Pi:$_Pi" => 输出当前shell的_Pi变量
#l ./1.sh => 等待三秒输出成功,说明先执行1.sh的父shell再执行2.sh的子shell
[root@server ~]# ./1.sh
_name:xjj => _name变量调用成功,说明export变量输出成功
_Pi: => _Pi变量无法调用成功,因为是局部变量
全局变量
可以使用export命令将本地变量输出为当前shell中的全局变量(注意:只在当前父shell及其子shell有效)
- 查看全局变量:
printenv命令
全局变量特点:
-
作用域:所有用户
-
生命周期:关机
-
应用场景:公共变量
-
永久定义:
/etc/profile
和/etc/bashrc
文件(用户登录前这两个文件就已经加载成功了)
备注:当全局变量和环境变量定义了同一个变量时以环境变量的定义为准。因为环境变量的文件后加载,所以会覆盖掉全局变量的文件中的变量
全局变量文件说明:
局部文件:作用于每个用户
$HOME/.bash_profile => 当前用户的环境变量
$HOME/.bashrc => 当前用户的bash信息(aliase、umask等)
全局文件:作用于全部用户
/etc/profile => 系统和每个用户的环境变量信息
/etc/bashrc => 使用bash shell用户全局变量
$HOME/.bash_logout => 每个用户退出当前shell时最后读取的文件
用户登录系统读取相关文件的顺序:
#l /etc/profile——> /etc/bashrc——> $HOME/.bash_profile——> $HOME/.bashrc——> $HOME/.bash_logout
全局环境变量 全局base shell信息 用户环境变量 用户base shell信息 用户退出时读取这个文件
如果想让修改过后的局部或全局文件生效需要重新加载:用source命令读取一下
# source /etc/bashrc => 让系统重新加载这个文件的配置,就会覆盖原来的
内置变量
系统变量(内置base变量):shell本身已经固定好了它的名字和作用
内置变量特点:
- 作用域:所有用户
- 生命周期:关机
- 应用场景:公共变量
内置变量说明:
#l $? :上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常 或出错
返回状态值:
0:表示命令执行成功
127:表示command not found
126:表示找到了该命令但无法执行(权限不够)
1或2:表示没有那个文件或目录
#l $$ :当前所在进程的进程号
#l $! :后台运行的最后一个进程号
#l !$ :调用最后一条命令历史中的参数
#l !! :调用最后一条历史命令
#l $# :脚本后面接的参数个数
#l $* :脚本后面所有参数,参数当成一个整体输出,每个变量参数之间以空格隔开
#l $@ :脚本后面所有参数,参数是独立的,也是全部输出
=> $*和$$的区别是一个是整体输出,一个是独立输出,可以用for i in $*(@);do echo $i;done,对脚本传参查看输出的值
#l $0 :当前执行的进程/程序名
#l $1~$9 :位置参数变量,应用于脚本外传参时,从外部传入参数到脚本内部执行
#l ${10}~${n} :扩展位置参数变量,第10个位置变量必须用{}大括号括起来
演示:
#l $? 变量返回上一条命令执行状态
[root@server ~]# ls
1 1.sh 2.sh
[root@server ~]# echo $?
0
[root@server ~]# lsls
bash: lsls: command not found...
[root@server ~]# echo $?
127
#l $$、$#、$*、$@ 变量的使用
[root@server ~]# vim demo.sh
#!/bin/bash
echo "\\$$=$$"
echo "\\$0=$0"
echo "\\$#=$#"
echo "\\$*=$*"
echo "\\$1=$1"
echo "\\$2=$2"
echo "\\$3=$3"
echo "\\$4=$4"
echo "\\$5=$5"
[root@server ~]# sh demo.sh a b c d e => 给五个参数,脚本外传参,给脚本内部执行
$$=39612 => 返回当前脚本所在进程PID
$0=demo.sh => 返回返回当前脚本进程的程序名
$#=5 => 返回参数个数
$*=a b c d e => 返回执行了哪些参数
$@=a b c d e => 返回执行了哪些参数
$1=a => 返回第1个参数
$2=b => 返回第2个参数
$3=c => 返回第3个参数
$4=d => 返回第4个参数
$5=e => 返回第5个参数
扩展:其他变量
当定义一个变量的内容是文件的时候,可以通过dirname和basename命令
去查看
扩展变量说明:
扩展说明:
取出有个目录下的目录和文件:dirname和basename
变量内容的输出和替换:
%:代表从右往左去掉一个/key/
%%:代表从右往左去掉最大的/key/,即保留最后一个以啥分隔左边内容
#:代表从左往右去掉一个/key/
##:代表从左往右去掉最大的/key/,即保留最后一个以啥分隔右边内容
*:匹配分隔符,后接分隔符号
演示:
#l 变量=文件路径:
[root@server ~]# A=/tem/base/shell/demo.sh => 定义变量值
[root@server ~]# echo $A => 正常读取
/tem/base/shell/demo.sh
[root@server ~]# dirname $A => 取出目录,通过"dirname"命令
/tem/base/shell
[root@server ~]# basename $A => 取出文件,通过"basename"命令
demo.sh
#l 获取变量,*代表匹配 、.代表分隔符
[root@server ~]# url=www.nbplus.com
[root@server ~]# echo $url
www.nbplus.com
[root@server ~]# echo ${#url} => "#" 获取变量长度
14
[root@server ~]# echo ${url#*.} => "#*." 以.为分隔符,从左往右去掉一个字段
nbplus.com
[root@server ~]# echo ${url#*n} => "#*n" 以n为分隔符,从左往右去掉一个字段
bplus.com
[root@server ~]# echo ${url##*.} => "##*." 以.为分隔符,从左往右去掉两
com
[root@server ~]# echo ${url%.*} => "%.*" 以.为分隔符,从右往左去掉一个字段
www.nbplus
[root@server ~]# echo ${url%%.*} => "%%.*" 以.为分隔符,从右往左去掉两个字段
www
变量取值
读取变量内容符:$
读取方法:$变量名
以上是关于shell编程之变量定义的主要内容,如果未能解决你的问题,请参考以下文章