• 【Shell 脚本速成】02、Shell 变量详解


    目录

    一、变量介绍

    变量存取原理

    二、变量定义

    2.1 什么时候需要定义变量?

    2.2 定义一个变量

    定义变量举例:

    定义变量演示: 

    2.3 取消变量 unset

    2.4 有类型变量 declare 

    declare 命令参数:

    案例演示:

    三、变量分类

    3.1 本地变量

    3.2 环境变量

    3.3 将当前变量变成环境变量 export

    3.4 父 shell 与子 shell

    总结:

    案例演示:

    3.5 全局变量

    3.6 内置变量

    案例演示:

    3.7 变量总结说明:

    四、变量取值

    五、其他变量(扩展)

    案例演示:


     

    一、变量介绍

            在编程中,我们总有一些数据需要临时存放在内存,以待后续使用时快速读出。先了解一下计算机的存储单位吧。

    1. 计算机的单位:
    2. 1B=8bit
    3. 1KB=1024B
    4. 1MB=1024KB
    5. 1GB=1024MB
    6. 1TB=1024GB
    7. 1PB=1024TB
    8. 1EB=1024PB
    9. 1ZB=1024EB
    10. ...
    11. 好了,已经够大了!当然还有YB、BB更大的单位,同样进制也是1024.
    12. 1G=1024*1024*1024=1073741824B

            假如你将一个1B的字符存入内存,如何读出呢?有没有一种大海捞针的感觉啊!我们讨论一下计算机是如何通过让我们人类快速将数据存在内存,如何从内存中读出数据的。我们研究过变量后就明白了。

    变量:变量是编程中最常用的一种临时在内存中存取数据的一种方式。

    变量存取原理

    1. 关于内存的说明
    2. a、系统启动:内存被按照1B一个单位划分成N块,并且以十六进制为每一个空间编号
    3. b、内存跟踪表记录:使用和未使用的内存的地址编号
    4. c、内存申请:系统从未使用的内存中拿出一个或者一段连续空间给你使用,同时在内存跟踪表中记录;该地址被占用不在分给别人,同时在系统中建立映射机制
    5. 比如:变量名 STRING1=‘ABC’
    6. name<==>0x5
    7. d、释放内存
    8. 从内存跟踪表中将记录删除,下次存数据直接覆盖

    1. CHAR1(0x3)=A
    2. 从图片可以看出,当我们在脚本中定义变量存值的时候,可以从以下方面看到变化:
    3. a、内存占用:如果存的是一个字符则占用1个字节,如果存的是字符串则是字符串的长度加1个字节长度(\0是一个特殊字符,代表字符串结束)。
    4. b、变量名与内存空间关系:计算机中会将对应的内存空间地址和变量名称绑定在一起,此时代表这段内存空间已经被程序占用,其他程序不可复用;然后将变量名对应的值存在对应内存地址的空间里。

    二、变量定义

    2.1 什么时候需要定义变量?

    1. 如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。
    2. 在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。

    2.2 定义一个变量

    变量格式: 变量名=值

    shell编程中的变量名和等号之间不能有空格。

    1. 变量名命名规则:
    2. 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
    3. 中间不能有空格,可以使用下划线 "_"
    4. 不能使用标点符号。
    5. 不能使用bash里的关键字(可用help命令查看保留关键字)。

    定义变量举例:

    • VAR1=1
    • age=18              整数(形)
    • name=‘baism’    字符串
    • score=88.8         浮点

    注意:字符串要用单引号或双引号引起来;建议变量名为大写,和命令区分,如 LS 或 _ls 

    定义变量演示: 

    1. # 变量赋值,此种方法设置为本地变量(临时生效,重启失效)
    2. [root@sql-master ~]# _name='sky'
    3. [root@sql-master ~]# age=18
    4. [root@sql-master ~]# echo $_name
    5. sky

    2.3 取消变量 unset

    1. # 取消当前环境中的变量,如果是变量设置是保存在文件中,下次重启又会恢复
    2. [root@sql-master ~]# unset _name
    3. [root@sql-master ~]# echo $_name

    2.4 有类型变量 declare 

    declare 命令参数:

    • -i 将变量看成整数
    • -r 使变量只读 readonly,该变量的值无法改变,并且不能使用unset
    • -x 标记变量通过环境导出 export(全局变量)
    • -a 指定为索引数组(普通数组);查看普通数组
    • -A 指定为关联数组;查看关联数组

    案例演示:

    1.定义变量为整数

    1. [root@sql-master ~]# echo $_name
    2. 0
    3. [root@sql-master ~]# _name=100.99
    4. -bash: 100.99: 语法错误: 无效的算术运算符 (错误符号是 ".99"
    5. [root@sql-master ~]# _name=100
    6. [root@sql-master ~]# echo $_name
    7. 100

    2.定义变量为只读模式

    1. [root@sql-master ~]# declare -r test='sky01'
    2. [root@sql-master ~]# echo $test
    3. sky01
    4. [root@sql-master ~]# test=123
    5. -bash: test: 只读变量
    6. [root@sql-master ~]# unset test
    7. -bash: unset: test: 无法反设定: 只读 variable

     

    三、变量分类

    系统中的变量根据作用域及生命周期可以分为四类:本地变量、环境变量、全局变量、内置变量

    3.1 本地变量

    用户自定义的变量,定义在脚本或者当前终端(会话)中,脚本执行完毕或终端(会话)结束变量失效。

    3.2 环境变量

    定义在用户家目录下的.bashrc或.bash_profile文件中,用户私有变量,只能本用户使用。

    • 查看当前用户的环境变量        env
    • 查看当前用户的所有变量(临时变量与环境变量)         set

    3.3 将当前变量变成环境变量 export

    1. # 定义一个临时变量,临时将一个本地变量(临时变量)变成环境变量(全局变量)
    2. [root@sql-master ~]# export A=hello
    3. [root@sql-master ~]# env | grep ^A
    4. # 定义一个永久生效变量:
    5. vim .bash_profile 或者 ~/.bashrc
    6. A=hello

    3.4 父 shell 与子 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的环境。

    案例演示:

    1. [root@sql-master ~]# age=20
    2. [root@sql-master ~]# export neme='sky'
    3. [root@sql-master ~]# vim test_02.sh
    4. #!/bin/bash
    5. echo $age
    6. echo $neme
    7. [root@sql-master ~]# bash test_02.sh
    8. sky

    3.5 全局变量

    • 使用export命令将本地变量输出为当前shell中的环境变量(临时有效)
    • 所有用户及shell都可以使用,可以在 /etc/profile 下永久定义
    1. # 打印全局变量 printenv
    2. [root@sql-master ~]# printenv
    3. # 定义永久变量
    4. [root@sql-master ~]# vim /etc/profile
    5. name='root'
    6. export name
    7. [root@sql-master ~]# source /etc/profile
    8. # 测试方法:通过不同用户登录测试是否能读取变量
    9. [root@sql-master ~]# echo $name
    10. root
    11. [root@sql-master ~]# su - tuschool
    12. [root@sql-master ~]# echo $name
    13. root

    3.6 内置变量

    系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用

    1. $?:输出上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
    2. 若退出状态值为0,表示命令运行成功
    3. 若退出状态值为127,表示command not found
    4. 若退出状态值为126,表示找到了该命令但无法执行(权限不够)
    5. 若退出状态值为1&2,表示没有那个文件或目录
    6. $$:当前所在进程的进程号 echo $$ eg:kill -9 `echo $$` = exit 退出当前会话
    7. $!:后台运行的最后一个进程号 (当前终端) # gedit &
    8. !$:调用最后一条命令历史中的参数
    9. !!:调用最后一条命令历史
    10. $#:脚本后面接的参数的个数
    11. $*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
    12. $@: 脚本后面所有参数,参数是独立的,也是全部输出
    13. $0:当前执行的进程/程序名 echo $0
    14. $1~$9:位置参数变量
    15. ${10}~${n}:扩展位置参数变量 第10个位置变量必须用{}大括号括起来

    案例演示:

    1. [root@sql-master ~]# vim 1.sh
    2. #!/bin/bash
    3. echo "\$0 = $0"
    4. echo "\$# = $#"
    5. echo "\$* = $*"
    6. echo "\$@ = $@"
    7. echo "\$1 = $1"
    8. echo "\$2 = $2"
    9. echo "\$3 = $3"
    10. echo "\$11 = ${11}"
    11. echo "\$12 = ${12}"
    12. [root@sql-master ~]# sh 1.sh a b c d e f g h i j k l m n

     

    3.7 变量总结说明:

    • 本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
    • 环境变量:当前进程有效,并且能够被子进程调用。
    • 全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用。
    • 内置变量:shell本身已经固定好了它的名字和作用。
    变量类型作用域生命周期
    本地变量当前shell环境(子shell不能用)脚本结束或终端结束
    环境变量当前shell或者子shell当前进程结束
    全局变量所有用户及shell环境关机
    内置变量所有用户及shell环境关机

    四、变量取值

    读取变量内容符:$

    读取方法:$变量名

    1. # 变量内容读出例子,前提是这些变量提前定义了
    2. [root@sql-master ~]# echo $name
    3. baism
    4. [root@sql-master ~]# echo $school
    5. ayitula
    6. [root@sql-master ~]# echo $age
    7. 30
    8. [root@sql-master ~]# echo $score
    9. 88.8
    10. # 注意:变量读取过程中,默认单引号是不解释变量的,比如
    11. [root@sql-master ~]# echo '$name'
    12. $name
    13. # 如果必须使用单引号还要读取变量的值可以使用 eval 命令[重新运算求出参数的内容]
    14. [root@sql-master ~]# eval echo '$name'
    15. baism

    五、其他变量(扩展)

    1. 1)输出目录路径和该路径下的文件名称:dirname 和 basename
    2. 2)变量内容输出参数:
    3. 一个 “%” 代表从右往左去掉一个/key/
    4. 两个 “%%” 代表从右往左最大去掉/key/
    5. 一个 “#” 代表从左往右去掉一个/key/
    6. 两个 “##” 代表从左往右最大去掉/key/

    案例演示:

    1.输出目录和文件名

    1. [root@sql-master ~]# vi 2.sh
    2. #!/bin/bash
    3. A=/usr/local/mycat/version.txt
    4. echo "上一级目录:`dirname $A`"
    5. echo "文件名:`basename $A`"
    6. [root@sql-master ~]# sh 2.sh
    7. 上一级目录:/usr/local/mycat
    8. 文件名:version.txt

    2.输出变量的长度

    1. [root@sql-master ~]# url=www.baidu.com
    2. [root@sql-master ~]# echo ${#url} # 获取变量的长度
    3. 13
    4. [root@sql-master ~]# echo ${url#*.} # 以分隔符 "." 为界限 , *:匹配所有
    5. baidu.com
    6. [root@sql-master ~]# echo ${url##*.}
    7. com
    8. [root@sql-master ~]# echo ${url%.*}
    9. www.baidu
    10. [root@sql-master ~]# echo ${url%%.*}
    11. www

     上一篇文章:【Shell 脚本速成】01、编程语言与 Shell 脚本介绍_Stars.Sky的博客-CSDN博客

    参考文档:shell变量详解-组团学

  • 相关阅读:
    如何搭建一个好的知识库管理系统?
    求余数联系和赋值运算
    微服务(基础篇-006-Docker安装-CentOS7)
    这是一段神奇的提示词,能直接调取Claude 3的系统提示词!附详细解读
    linux安装redis(保姆级-安装包方式安装-版本6.2.7-解决aof持久化问题)
    固态硬盘有缓存和没缓存之间的区别在哪
    LeetCode 1334. 阈值距离内邻居最少的城市:多次运用单源最短路的迪杰斯特拉算法
    51单片机学习:直流电机实验
    【LeetCode热题100】--148.排序链表
    数据结构:平衡二叉树
  • 原文地址:https://blog.csdn.net/weixin_46560589/article/details/127983534