原创文章,欢迎转载。转载请注明:转载自 祥的博客
原文链接:https://blog.csdn.net/humanking7/article/details/84641588
环境
ubuntu 16.04
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
1. 概述
变量可分为两类:环境变量(全局变量)
和 普通变量(局部变量)
。
环境变量
也可称为全局变量
,可以在创建它们的Shell
及其派生出来的任意子进程Shell
中使用,环境变量又可分为自定义环境变量
和bash内置的环境变量
。普通变量
也可称为局部变量
,只能在创建它们的Shell函数
或Shell脚本
中使用。普通变量
一般由开发者在开发脚本程序时创建。
默认情况下,在bash Shell
中是 不会区分变量类型 的,例如常见的变量类型为整数
、字符串
等。这和其他强类型语言
(比如C语言
等)是有区别的。当然,如果需要指定Shell变量
的类型,也可以使用declare -p
显示定义变量的类型,但在一般情况下没有这个需求。
root@vultr:~# echo $HOME
/root
root@vultr:~# declare -p HOME
declare -x HOME="/root"
2. 环境变量
环境变量
一般是指用export
内置命令导出的变量(运行export -p
可以查看)。
所有的环境变量
都是系统全局变量
,可用于所有子进程
中,这包括编辑器
、Shell脚本
和各类应用
。
环境变量
可以在命令行
中设置和创建,但用户退出命令行
时这些变量值就会丢失
,如果希望 永久保存 环境变量
,可在用户 家目录 下的.bash_profile
或.bashrc
(非用户登录模式
特有,如远程SSH
)文件中,或者全局配置/etc/bashrc
(非用户登录模式特有
,如远程SSH
)或 /etc/profile
文件中定义。在将环境变量
放入上述的文件中后,每次用户登录时这些变量
都将被初始化
。
按照系统规范,所有环境变量
的名字均采用大写形式
。在将环境变量
应用于用户进程程序之前,都应该用export
命令导出定义。
有一些环境变量,比如HOME
、PATH
、SHELL
、UID
、USER
等,在用户登录之前就已经被/bin/login
程序设置好了。通常环境变量被定义并保存在用户家目录下的.bash_profile
文件或全局的配置文件/etc/profile
中。
# 定义一个环境变量 MY_BLOG
root@vultr:~# export MY_BLOG="http://blog.csdn.net/humanking7/"
# 显示环境变量(中间删去了一些显示内容)
root@vultr:~# export -p
declare -x MY_BLOG="http://blog.csdn.net/humanking7/"
declare -x HOME="/root"
declare -x LANG="en_US.UTF-8"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LOGNAME="root"
declare -x MAIL="/var/mail/root"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
declare -x PWD="/root"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_TTY="/dev/pts/2"
declare -x TERM="xterm"
declare -x USER="root"
declare -x XDG_DATA_DIRS="/usr/local/share:/usr/share:/var/lib/snapd/desktop"
2.1. 与环境变量相关的命令
有5
个命令都与变量
有关
set
unset
env
declare
export
readonly
set
命令会输出所有的变量
(全局变量
和 局部变量
),直接在shell
中输入set
,会有很多的数据输出,建议用set | less
进行查看,使用set | wc -l
可以发现一共有2106
行数据,而且本身set
命令也有很多选项和玩法,以后在慢慢研究。其中set -o
会显示bash shell
的所有参数配置信息。
env
命令只会显示全局变量
。
declare
命令会输出所有的变量
、函数
、整数
和已经导出的变量
。用declare | wc -l
一查还是2106
行,declare
本身是可以声明、取消、查看变量类型的,也有很多玩法。
export
命令,对于查看shell
赋予程序的环境变量,我是特别喜欢用export -p
进行显示,非常清爽。
readonly 变量名
,将设置变量为只读变量
,出于安全的原故,只读变量是不可以
被复位/取消
的,只有等到shell
注销。
unset
命令可以清除环境变量
,而且set
,env
,export
设置的变量,都可以用它来清除。
# 设置环境变量
root@vultr:~# export MY_BLOG="http://blog.csdn.net/humanking7/"
root@vultr:~# env | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
root@vultr:~# set | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
root@vultr:~# export -p | grep MY_BLOG
declare -x MY_BLOG="http://blog.csdn.net/humanking7/"
root@vultr:~# declare | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
# 将变量设置为只读
root@vultr:~# readonly MY_BLOG
# 只读变量无法改变和删除
root@vultr:~# export MY_BLOG="csdn"
-bash: MY_BLOG: readonly variable
root@vultr:~# unset MY_BLOG
-bash: unset: MY_BLOG: cannot unset: readonly variable
# 设置一个环境变量,然后清除
root@vultr:~# export WEB_SITE=google.com
root@vultr:~# env | grep WEB_SITE
WEB_SITE=google.com
root@vultr:~# unset WEB_SITE
root@vultr:~# env | grep WEB_SITE
root@vultr:~#
2.2. 自定义环境变量
# 方法1
export variableName=value
# 方法2
declare -x variableName=value
上述的两个方法也是重新赋值的方法,示例如下:
root@vultr:~# export MY_NAME=Q
root@vultr:~# env | grep MY_NAME
MY_NAME=Q
root@vultr:~# declare -x MY_NAME=F
root@vultr:~# env | grep MY_NAME
MY_NAME=F
root@vultr:~# export MY_NAME=A
root@vultr:~# env | grep MY_NAME
MY_NAME=A
2.3. 让环境变量永久生效
如果希望环境变量
永久生效,则可以将 环境变量
放在用户环境变量文件
或全局环境变量文件
里。
让环境变量永久生效的常用设置文件
2.3.1. 用户环境变量配置
家目录(比如说家目录是/root/
)下的两个文件中写入环境变量
(随便一个就可以)
/root/.bashrc
/root/.bash_profile
2.3.2. 全局环境变量配置
常见的全局环境变量
的配置文件如下:
/etc/bashrc # 推荐在此文件中优先设置
/etc/profile
/etc/profile.d/
2.4. 启动顺序
Shell
的初始化过程
是这样的:
bash
检查文件/etc/profile
(默认的Shell
主环境变量文件,每个用户登录都会加载)是否存在,存在
就读取环境变量,否则跳过;- 当加载完
/etc/profile
文件后,才会执行/etc/profile.d/
目录下的脚本文件
,这个目录下的脚本文件有很多
; - 之后
bash
检查家目录$HOME
下的文件.bash_profile
(用户环境变量文件)是否存在,存在
就读取环境变量,否则跳过; - 又会去找
$HOME/.bashrc
(用户环境变量文件),存在
就读取环境变量,否则跳过。 - 在
$HOME/.bashrc
文件中又会去找/etc/bashrc
(全局环境变量文件),存在
就读取环境变量,否则跳过。
注意:
如果用户的Shell
不是登录时启动
的(比如手动敲下bash
时启动 或者 其他不需要输入密码的登录
及 远程SSH连接
情况),那么这种非登录Shell
只会加载$HOME/.bashrc
(用户环境变量文件),并会去找/etc/bashrc
(全局环境变量文件)。因此如果希望在非登录Shell
下也可读到设置的环境变量
等内容,就需要将变量
设定等写入$HOME/.bashrc
或者/etc/bashrc
,而不是$HOME/.bash_profile
或/etc/profile
。
2.5. 小结
环境变量
的知识(见参考文献1 ):
变量名
通常要大写。- 变量可以在自身的
Shell
及子Shell
中使用。 - 常用
export
来定义环境变量
。 - 执行
env
默认可以显示所有的环境变量名称
及对应的值
。 - 输出时用
“$变量名”
,取消时用“unset变量名”
。 - 书写
crond
定时任务时要注意,脚本要用到的环境变量最好先在所执行的Shell
脚本中重新定义。 - 如果希望
环境变量
永久生效,则可以将其放在用户环境变量文件
或全局环境变量文件
里。
3. 普通变量
3.1. 定义
本地变量
在用户当前Shell生存期的脚本
中使用。如果在Shell
中启动另一个进程
或退出
,那么变量
将会失效。
有3
种定义方法:
# 赋值时不加引号
variableName=value
# 赋值时加单引号
variableName='value'
# 赋值时加双引号
variableName="value"
变量
的内容可以用单引号
或双引号
引起来,也可不加引号
,但是这三者的含义是不同的。
3.2. 输出及其显示
$变量名
表示输出变量
,可以用$变量名
和${变量名}
两种用法。
3.2.1. 例子1
#!/bin/bash
# author:Q
# url:http://blog.csdn.net/humanking7/
var1=2018
var2='2018'
var3="2018"
echo "var1=$var1"
echo "var2=$var2"
echo "var3=${var3}"
运行结果:
root@vultr:~# ./t2.sh
var1=2018
var2=2018
var3=2018
3.2.2. 例子2
#!/bin/bash
# author:Q
# url:http://blog.csdn.net/humanking7/
var1=2018
var1=2018-$var1
var2='2018-$var1'
var3="2018-$var1"
echo "var1=$var1"
echo "var2=$var2"
echo "var3=${var3}"
运行结果:
root@vultr:~# ./t2.sh
var1=2018-2008
var2=2018-$var1
var3=2018-2018-2008
分析:
第1
种定义方式,var1
,是不加任何引号
直接定义变量的内容(值)
。当内容
为 简单连续的数字
、字符串
、路径名
时,可以这样用。不加引号时,值
里有变量
的 会被解析后再输出,上述变量定义中因为$var1
的值被解析为2018
,因此新的var1
值就是2018-2018
。
第2
种定义方式,通过单引号
定义。这种定义方式的特点就是,单引号里面是什么,输出内容就是什么,即使内容(值)
里面有变量
或者命令
(命令需要反引号引起来)。所以对var2
定义是2018-$var1
,最终也是原样输出。
第3
种定义方式,通过双引号
定义。这种定义方式的特点是,输出变量内容时引号里的变量及命令会经过解析后再输出内容。这种方式比较适合于字符串
中附带有变量
及命令
且想将其解析后
再输出的变量定义。
Tip:
数字内容
的变量定义可以不加引号
;- 其他没有特别要求的
字符串
等定义最好都加上双引号
; - 如果真的需要
原样输出
就加单引号
。
3.3. 把命令的结果作为变量的内容赋值的方法
对需要获取命令结果的变量内容赋值的常见方法有2种:
# 方法1
# 把命令用反引号引起来,不推荐使用这种方法,因为容易和单引号混淆
variableName=`ls`
# 方法2
# 把命令用$()括起来,推荐使用这种方法
variableName=$(ls)
方法1:
root@vultr:~# ls -1
code
control_vpn
restart_ss.sh
showUsed_ss.sh
t2.sh
root@vultr:~# cmd=`ls -1`
root@vultr:~# printf "$cmd"
code
control_vpn
restart_ss.sh
showUsed_ss.sh
方法2:
root@vultr:~# cmd2=$(ls -1)
root@vultr:~# printf "$cmd2"
code
control_vpn
restart_ss.sh
showUsed_ss.sh
3.4. 注意
单独拎出来写一个小节,觉得是这个有点重要。
在变量名
前加$
可以取得该变量的值
,使用echo
或 printf
命令可以显示变量的值
,$变量名
和${变量名}
的写法不同,但效果是一样的。
当变量
后面连接有其他字符的时候,必须给变量加上大括号{}
,如下面的例子:
root@vultr:~# var1='my '
root@vultr:~# var1name=csdn
root@vultr:~# echo $var1name
csdn
root@vultr:~# echo ${var1}name
my name
Tip:
数字内容
的变量定义可以不加引号
;- 其他没有特别要求的
字符串
等定义最好都加上双引号
; - 如果真的需要
原样输出
就加单引号
。 - 希望
变量值引用命令
并获取命令的结果时就用反引号
或$()
4. 例子
例子1:
root@vultr:~# echo "today : `date`"
today : Thu Nov 29 14:07:43 UTC 2018
root@vultr:~# echo "today : $(date)"
today : Thu Nov 29 14:07:57 UTC 2018
例子2:
# test.txt 文件里面有6行内容
# 其中有2行包含变量var1的值"csdn"
# 其中有2行包含"$var1",这个字符串
root@vultr:~# cat test.txt
csdn
https://blog.csdn.net/humanking7/
baidu.com
google.com
$var1
$var1name
# 定义一个变量
root@vultr:~# var1=csdn
# 查找变量"值" 与 文件匹配的内容
root@vultr:~# grep $var1 test.txt
csdn
https://blog.csdn.net/humanking7/
root@vultr:~# grep ${var1} test.txt
csdn
https://blog.csdn.net/humanking7/
root@vultr:~# grep "$var1" test.txt
csdn
https://blog.csdn.net/humanking7/
# 查找字符串"$var1" 与 文件匹配的内容
root@vultr:~# grep '$var1' test.txt
$var1
$var1name
5. 参考文献:
OK!
以上,Enjoy~