深入浅出的学习变量(局部、全局、系统、位置、只读变量... set 命令、export 命令、以及如何设置环境变量!)

Jill ·
更新时间:2024-09-20
· 501 次阅读

文章目录变量?变量的赋值:①、静态语言 或 强类型②、动态语言 或 弱类型变量名命名规则? ==bash 中 变量的种类:==①、局部变量:★ 如何使用局部变量?★ 如何证明局部变量的生效范围?①、首先 使用 set 命令查看所有变量:②、接着 使用 bash 命令 进入当前shell 的子shell 进程:③、然后 使用 pstree -p 来查看进程之间的树状关系图:④、最后 使用 exit 命令退出当前 shell进程:②、全局变量(环境变量):★ 常用的全局变量:★ 使用关键字 export 来定义全局变量:★ 使用 “declare -x” 定义全局变量:★ 使用 export 来查看所有环境变量:★ 使用 evn 命令 查看所有环境变量★☆★_注意:局部和全局变量只能父传子,子不能传父!③、特殊变量(系统变量):★ 系统变量图表:★ $* 和 $@ 的区别是什么?④、只读变量:★ 如何声明只读变量:★ 如何查看只读变量:⑤、位置变量:★ 使用   \$1...$n 来表示位置变量★ 简单使用 位置变量 和 系统变量做一个例子:★ 用 $10 等十位数作为位置变量的时候,使用 { } !★ 使用 shift 往前移动位置变量的参数: ★★★ 使用 set 命令查看已经定义的所有变量:★★★ 使用 unset 来删除变量:★★★ 使用 set - - 清空位置变量:★★★ 使用 “”(双引号)来保证变量内容的格式! ★★★ Linux下设置环境变量:☆ 为什么要设置环境变量?用户级别环境变量定义文件:① 使用 export PATH ==(仅对当前用户和当前终端有效)==② vim ~/.bashrc ==(仅对当前用户永久生效)==③ vim ~/.profile ==(仅对当前用户永久有效)==系统级别环境变量定义文件:① vim /etc/bashrc ==(对所有用户永久生效)==② vim /etc/profile ==(对所有用户永久有效)==③ vim /etc/environment ==(对所有用户永久有效)== Linux 中环境变量加载解析:

这里是自己写的一个 shell入门到放弃 的一个目录导航!因为本章是学习shell 接触的变量,所以这里的例子都是在 bash shell 中使用 变量。
 

变量?

        顾名思义,变量变量就是可以变化的量!当然这是一句废话!

举例:
        当我们想使用内存空间中的字符串“aaa”的时候,那么在内存空间中就有一个这个字符串“aaa”的地址,在计算机里,存放数据都为二进制格式“010101…”,对于计算机来说,使用“010101…”这个地址很简单,但是对于我们用户来说,那么多字符串的地址我们怎么可以记得住,为了方便就使用变量!

格式:     值类型 varname=“值”(静态语言)
                或
                varname=“值”(动态语言)

 

变量的赋值:

       

①、静态语言 或 强类型

        在使用变量的时候,必须声明 变量的类型
        eg: C++、java…

int varname=100; int 大家都知道是指定 "整数类型" 的一个 "函数" ②、动态语言 或 弱类型

        在使用变量的时候,不需要声明 变量的类型 变量的类型一般就是被赋值的那个值的类型!
        eg:Python、PHP、shell…

varname=100; 100是整数,所以这里 varname 的类型就为 int 变量名命名规则?

①、不建议使用程序中的保留字:例如 if、for…

root@zhengzelin:~# type if if is a shell keyword(关键字) "可以使用,但是不建议使用。"

②、只能使用数字、字母、下划线,不能使用数字开头

root@zhengzelin:~# n1=aaa (√) root@zhengzelin:~# 1n=aaa (×) 1n=aaa: command not found root@zhengzelin:~# n?=aaa (×) n?=aaa: command not found

③、驼峰命名法

在命名变量名的时候,每个人的格式不一样;假如定义一个变量名为 my name , 可能出现的格式:myname、my_name、MyName或者myName。 这样的命名规则不适合所有程序员阅读,而利用驼峰命名法来表示,可以增加程序可读性。例如: "大驼峰" —— 所有单词的首字母都大写: myname = MyName "小驼峰" —— 第一个单子首字母小写,后续大写:myname =myName 如果你的上头要求用什么格式写就按什么格式写,没要求就按 “驼峰命名法”   bash 中 变量的种类:

 
注意:这里说到了是 shell 中的 bash shell ,其他的shell有一点细微区别!
 

①、局部变量:

        顾名思义,就是局部范围内有效只在 当前shell进程 生效(包括其子进程都不生效)。

        同理:在子shell创建的变量 ,在父shell 里也不生效!

★ 如何使用局部变量? a=1 #这就是一个局部变量,最为简单,直接赋值即可! ★ 如何证明局部变量的生效范围? ①、首先 使用 set 命令查看所有变量: 首先,在当前shell 创建一个变量: root@zhengzelin:~# a=1 root@zhengzelin:~# echo $a 1 root@zhengzelin:~# set | grep "^a" a=1 ②、接着 使用 bash 命令 进入当前shell 的子shell 进程: # bash 命令是在后台执行,并不影响其他命令的使用。 root@zhengzelin:~# echo $$ # 查看当前 shell进程 的 PID号 23905 root@zhengzelin:~# bash # 再次打开一个shell进程,也就是当前shell进程的子进程 root@zhengzelin:~# echo $$ # 查看当前 shell进程 的 PID号 23921 root@zhengzelin:~# echo $PPID # 查看当前shell进程的父shell进程的PID 23905 之前的 变量a 是在当前 shell进程 的父进程内命名的, 在当前shell 中查看 之前的变量 a 是否存在: root@zhengzelin:~# set | grep ^a [空] "发现此时的 变量a 不复存在!证明了局部变量的范围!" 如何返回当前子shell进程 的父进程? 下面会使用: ③、然后 使用 pstree -p 来查看进程之间的树状关系图: root@zhengzelin:~# echo $$ # 本 shell 的进程 23921 root@zhengzelin:~# echo $PPID # 父shell的进程 23905 root@zhengzelin:~# pstree -p systemd(1) |........(省略...) ├─sshd(963)───sshd(23887)───bash(23905)───bash(23921)───pstree(23936) 可以很清楚的看见: 23905 和 23921 的关系。 ④、最后 使用 exit 命令退出当前 shell进程: 返回当前 shell 进程 的父shell进程: root@zhengzelin:~# echo $PPID 23905 root@zhengzelin:~# echo $$ 23921 root@zhengzelin:~# exit exit root@zhengzelin:~# echo $$ 23905 再次查看之前的变量a root@zhengzelin:~# set | grep ^a a=1 ②、全局变量(环境变量):

        生效范围 为 当前shell进程 及其 子shell 进程。

★ 常用的全局变量:
变量名 作用 用法
PATH 定义了 运行命令的查找路径 echo $PATH
HOME 显示当前用户所在的家目录 同上
SHELL 显示当前的 shell类型 同上
SHLVL 显示当前shell进程的嵌套深度 同上
USER 显示当前的 username 同上
HISTSIZE 输出的历史命令记录条数 同上
HISTFILESIZE 显示 保存的历史命令记录条数 同上

eg:使用 SHLVL 变量:

root@zhengzelin:~# echo $SHLVL # 查看当前嵌套的shell进程 1 root@zhengzelin:~# bash # 进入子shell 进程 root@zhengzelin:~# echo $SHLVL 2 ★ 使用关键字 export 来定义全局变量: "要想定义全局变量,必须使用一个关键字": export 这里的步骤和原理 与 上面测试局部变量生效范围 的原理是一样的; 就不做一一解释了: root@zhengzelin:~# echo $$ 23905 root@zhengzelin:~# export name=1 # 定义全局变量 root@zhengzelin:~# bash root@zhengzelin:~# echo $$ 24158 root@zhengzelin:~# echo $PPID 23905 root@zhengzelin:~# echo $name 1 root@zhengzelin:~# exit exit 由此可以证明 全局变量的生效范围:当前shell进程及其子shell进程都生效! 那么在 子 shell 中创建的 全局变量,父 shell 里还可以生效吗: root@zhengzelin:~# echo $$ 24252 root@zhengzelin:~# bash root@zhengzelin:~# export b=111 root@zhengzelin:~# env | grep ^b b=111 root@zhengzelin:~# echo $$ 24267 root@zhengzelin:~# echo $PPID 24252 root@zhengzelin:~# exit exit root@zhengzelin:~# echo $$ 24252 root@zhengzelin:~# echo $b [空] "只能父进程传给子进程,子进程不能传给父进程!" ★ 使用 “declare -x” 定义全局变量: 这里就不做解释了,自己可以动手敲一敲! ★ 使用 export 来查看所有环境变量: 当你使用 export ,后面不加变量名的时候,这就代表查看所有环境变量: root@zhengzelin:~# export ....... declare -x TERM="xterm" declare -x USER="root" declare -x a="2" ....... "为什么前面是 declare -x 呢? 其实使用 “declare -x” 也可以定义全局变量!" ★ 使用 evn 命令 查看所有环境变量 root@zhengzelin:~# env XDG_SESSION_ID=3906 USER=root MAIL=/var/mail/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games PWD=/root LANG=en_US.UTF-8 SHLVL=3 HOME=/root ...... ★☆★_注意:局部和全局变量只能父传子,子不能传父! ③、特殊变量(系统变量): ★ 系统变量图表:
系统变量 作用
$0 当前脚本的名字
$* 当前脚本的 所有参数(不包括程序本身)
$@ 也是表达所有参数,但是与 $* 有区别,下面会讲
$# 当前脚本的 参数个数(不包括程序本身)
$? 程序或命令执行完的状态,返回值为 0 表示执行成功
$$ 程序本身的 PID
$PPID 当前 shell进程 的 父进程 的 PID 号
★ $* 和 $@ 的区别是什么?

注意:$* 和 $@ 只有被双引号(" ") 引起来的的时候才有区别!( “$*” 和 “$@”)

"①、 $* :传递给脚本的参数,所有参数合并为一个字符串!" "②、 $@ : 传递给脚本的所有参数,每个参数为独立的字符串!" 直接举例: root@zhengzelin:~# vim a.sh #/bin/bash echo "this is first script's all variable : $*" # 这里就是显示此脚本的所有位置参数,这里使用 $* 和 $@ 都一样 ./b.sh "$*" # 在a脚本里面调用b脚本,b脚本里面去调用"$*" "这里的$* 指的就是 b 脚本的位置变量的参数" ★★★ 注意: 这里的第二个 $* 一定要用""(双引号) 括起来,不然提现不出来他们的区别! 查看一下 b脚本 的内容: root@zhengzelin:~# vim b.sh #/bin/bash echo "this is the first variable of the second script: $1" 直接来验证一下结果: root@zhengzelin:~# ./a.sh a b c this is first script's all variable : a b c this is the first variable of the second script: a b c (b脚本本来的位置变量是 $1,按照正常的结果来看应该输出的是"a" 啊,这里为什么是"a b c" 呢?) (这就是上面提到的: $* 是将"传递给脚本的所有参数合并为一个参数!") 既然都合为一个参数了,所以 "$1" 指的就是 "a b c" 那么我们来验证 "$@" : 将脚本a的 "$*" 换为 "$@": root@zhengzelin:~# cat a.sh #/bin/bash echo "this is first script's variable : $*" ./b.sh "$@" ———— # 只需要更换这个参数即可,这个是用来传递参数给另一个脚本的! "来看一下执行结果:" root@zhengzelin:~# ./a.sh a b c this is first script's all variable : a b c this is the first variable of the second script: a ④、只读变量:

        顾名思义,就是该变量只能读,不可以修改 和 删除!除非你结束程序它会自动消失。
       

★ 如何声明只读变量: readonly varname=value 或 declare -r varname=value declare -x varname=value # 这个是声明全局变量! ★ 如何查看只读变量: "readonly -p" root@zhengzelin:~# readonly -p declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath" declare -ir BASHPID declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")' declare -ir EUID="0" declare -ir PPID="24748" declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor" declare -ir UID="0" ⑤、位置变量:

        位置变量,这个很重要,一般我们写的变量都是写死的,这个位置变量可以使我们的脚本变得更加的灵活!
       

★ 使用   $1…$n 来表示位置变量 $1 : 第一个位置变量.. $2 : 第二个位置变量.. ... ★ 简单使用 位置变量 和 系统变量做一个例子: root@zhengzelin:~# cat a.sh #!/bin/bash echo `date +%F` echo -e "\033[1;36m start... \033[0m" echo "first number is $1" echo "second number is $2" echo "all number is $*" echo "all number‘s number is $#" echo "this script name is $0" echo -e "\033[1;36m stop... \033[0m" 然后使用位置变量:当然你可以换为其他数字或字符串 root@zhengzelin:~# ./a.sh 1 2 2020-03-20 start... first number is 1 second number is 2 all number is 1 2 all number‘s number is 2 this script name is ./a.sh stop... 这里发现 $0 表达1脚本名字会带路径 ./a.sh "然后可以使用 basename 来取消路径,只显示文件名:" root@zhengzelin:~# cat a.sh ....... echo "this script name is `basename $0`" (注意反撇号) root@zhengzelin:~# ./a.sh ..... this script name is a.sh (对比上面的输出结果发现路径没有了) ..... ★ 用 $10 等十位数作为位置变量的时候,使用 { } ! 首先看一下脚本内容: root@zhengzelin:~# cat a.sh #!/bin/bash echo `date +%F`; echo -e "\033[1;36m start... \033[0m" echo "first number is $9" echo "second number is $10" ———— 重要的 $10 在这里! echo "all number is $*" echo "all number‘s number is $#" echo "this script name is `basename $0`" echo -e "\033[1;36m stop... \033[0m" root@zhengzelin:~# ./a.sh a b c d e f g h i j k 2020-03-21 start... first number is i second number is a0 —————— 但是你发现这里的输出结果是 a0?为什么是a0呢? a在上面表示的位置是 $1,所以系统将 $10分为$1+0 所以这边的输出结果就为 : $10 = a0 避免这种情况的话就使用 "{ }" 将位置变量括起来: ${10} 我这就不演示了 ★ 使用 shift 往前移动位置变量的参数: 仅执行 shift ,代表往前移动一位位置变量的参数! 移动两位的话就是: shift 2 eg: root@zhengzelin:~# cat b.sh #/bin/bash echo "the first variable is : $1" echo "the second variable is : $2" shift echo "the third variable is :$3" root@zhengzelin:~# ./b.sh 1 2 3 4 5 the first variable is : 1 the second variable is : 2 the third variable is :4 #执行了 shift 之后,原来3就被跳过了 当你将原来的 shift 变为 shift 2 的时候,$3就变成了数组 5 !   ★★★ 使用 set 命令查看已经定义的所有变量: 记得是所有变量:局部变量 + 全局变量 查看全局: export 或 declare -x 或 env ★★★ 使用 unset 来删除变量: "格式: unset varname ,不需要加 $符号!" root@zhengzelin:~# export a=111 root@zhengzelin:~# unset $a | echo $? 1 -bash: unset: `1': not a valid identifier root@zhengzelin:~# unset a | echo $? 0 "结合特殊变量 “$?” 来查看结果" ★★★ 使用 set - - 清空位置变量: root@zhengzelin:~# cat b.sh #/bin/bash echo "the first variable is : $1" echo "the second variable is : $2" echo "the third variable is :$3" root@zhengzelin:~# ./b.sh a b c the first variable is : a the second variable is : b the third variable is :c 正常结果就是以上输出的结果,现在使用 "set --" 来清空下面的位置变量! root@zhengzelin:~# cat b.sh #/bin/bash echo "the first variable is : $1" set -- echo "the second variable is : $2" echo "the third variable is :$3" root@zhengzelin:~# ./b.sh a b c the first variable is : a the second variable is : the third variable is : ★★★ 使用 “”(双引号)来保证变量内容的格式! 当你的变量是一个文件或者一段有格式的内容的时候,如果你使用简单的 $varnmae 你会发现 当你 echo 它的时候,输出的结果为一段话,把多行内容合并在一起了! eg: root@zhengzelin:~# VarName=`cat /etc/fstab` root@zhengzelin:~# echo $VarName # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # # / was on /dev/vda1 during installation "这个时候就可以使用双引号了:" root@zhengzelin:~# echo "$VarName" # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # # / was on /dev/vda1 during installation .....   ★★★ Linux下设置环境变量: ☆ 为什么要设置环境变量?

        当你自定义安装一个软件的时候,当安装完成之后,你需要使用命令来对此软件执行操作,如果你没有设置环境变量的话,你就不能直接使用此命令!

        举例,假如你安装了 mysql,当你要使用 mysql 命令的时候,你发现你不能直接使用,除非你使用特定的格式才能执行命令(eg:/安装路径/…/mysql/bin),否则系统会提示没有此命令,这就是因为你没有设置 PATH 环境变量,此 环境变量的作用就是:系统会从 PATH环境变量里找执行那个命令的路径,如果这些路径里没有mysql命令,当然不能执行了!所以你就得使用命令 给他添加到 PATH环境变量里了!具体添加方法下面有介绍!
 

用户级别环境变量定义文件: ① 使用 export PATH (仅对当前用户和当前终端有效) 生效时间: "立即生效" 生效范围: "仅仅对当前shell进程 和 当前用户生效" ,关闭当前shell即失效! 格式 :export PATH=$PATH:/新的路径 root@zhengzelin:~# export PATH=$PATH:/tmp/zzl root@zhengzelin:~# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/tmp/zzl ② vim ~/.bashrc (仅对当前用户永久生效) # ubuntu 和 centos 中 文件名一样! 生效时间: 使用 "当前用户打开新的终端的时候生效" 或 使用 "source ~/.bashrc" 手动立即生效 格式:"vim ~/.bashrc" # 在最后一行加上 export PATH=$PATH:/tmp/zzl 添加了环境变量之后,可以使用"source 命令"来使你的配置文件立即生效 "source ~/.bashrc" ③ vim ~/.profile (仅对当前用户永久有效) Centos中: ~/.bash_profile Ubuntu中: ~/.profile # 和修改 ~/.bashrc 文件类似,也是在文件末添加新路径即可 # 使用同一个用户打开一个新的终端生效,或者 "source" 一下生效! 系统级别环境变量定义文件: ① vim /etc/bashrc (对所有用户永久生效) # 该方法是修改系统配置、需要 root 权限! Centos 中: /etc/bashrc Ubuntu 中: /etc/bash.bashrc root@zhengzelin:~# vim /etc/bash.bashrc # 在最后一行加上 : export PATH=$PATH:/new 生效方式: "source 位置即可" root@zhengzelin:~# source /etc/bash.bashrc 注意:如果 该文件不可编辑,需要改为可编辑!权限问题咯! ② vim /etc/profile (对所有用户永久有效) # Centos 和 Ubuntu 中 配置文件名字一样! 方法与上面的 "/etc/bashrc" 类似。 需要 root 权限,手动 source 生效, ③ vim /etc/environment (对所有用户永久有效) # 放法 及 权限 与 修改 /etc/profile 一样!   Linux 中环境变量加载解析:

 
本篇文件写的太长了,切换下一个文章来写吧!望理解!

戳我去学习 Linux中环境变量的加载过程


作者:郑泽林



环境 set export 学习 系统 深入浅出 环境变量 变量

需要 登录 后方可回复, 如果你还没有账号请 注册新账号