十、变量
变量的赋值方式
先写变量名称,紧接着是“=”这个字符,最后是值。中间无任何空格,通过echo命令加上$oldboy即可输出oldboy变量的值,变量的内容一般要加双引号,以防止出错。特别是当值里的内容之间有空格时。
$ oldboy='I am a boy'
$ echo $oldboy
I am a boy
shell变量的特性
默认情况下,在bash shell中是不会区分变量的类型的。但是如果需要指定shell变量的类型,也可以使用declare显示定义变量的类型。
变量类型
分为两类:环境变量(全局变量)和普通变量(局部变量)
环境变量(全局变量),可以在创建它们的shell及其派生出来的的任意子进程shell中使用,环境变量又可分为自定义环境变量和bash内置的环境变量。
普通变量(局部变量)只能在创建他们的shell函数或shell脚本中使用。普通变量一般由开发者在开发脚本程序时创建 。
十一、环境变量
环境变量定义
环境变量一般是指用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。shell通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等,所有的环境变量都是系统全局变量,可用于所有的子进程中,这包括编辑器、shell 脚本和各类应用。
环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,因此,如果希望永久保存环境变量,可在用户家目录下的.bash_profile或.bashrc(非用户登录模式特有,例如远程ssh)文件中,或者全局配置/etc/bashrc(非用户登录模式特有,例如远程ssh)或/etc/profile文件中定义。在将环境变量放入上述的文件中后,每次用户登录时这些变量都将被初始化。
按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用export命令导出定义,例如:正确的环境变量定义方法为export OLDGIRL=1。
有一些环境变量,比如HOME、PATH、SHELL、UID、 USER等,在用户登录之前,就已经被/bin/login程序设置好了。通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中。
常见的环境变量:
PATH: 决定了shell将到哪些目录中寻找命令或程序
ROOTPATH: 这个变量的功能和PATH相同,但它只罗列出超级用户(root)键入命令时所需检查的目录。
HOME: 当前用户主目录
USER: 查看当前的用户
LOGNAME: 查看当前用户的登录名。
UID: 当前用户的识别字,取值是由数位构成的字串。
SHELL: 是指当前用户用的是哪种Shell。
TERM : 终端的类型。
PWD: 当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化。
MAIL: 是指当前用户的邮件存放目录。
HISTSIZE: 是指保存历史命令记录的条数
HOSTNAME: 是指主机的名称,许多应用程序如果要用到主机名的话,通常是从这个环境变量中来取得的。
PS1: 是基本提示符,对于root用户是#,对于普通用户是$,也可以使用一些更复杂的值。
PS2: 是附属提示符,默认是“>”。可以通过修改此环境变量来修改当前的命令符,比如下列命令会将提示符
修改成字符串“Hello,My NewPrompt :) ”。# PS1=" Hello,My NewPrompt :)"
IFS: 输入域分隔符。当shell读取输入时,用来分隔单词的一组字符,它们通常是空格、制表符和换行符。
_=: 上一条命令的最后一个参数
在查看设置的变量时,有三个命令可以显示变量的值:set、env和declare(替代早期的typeset)。set命令输出所有的变量,包括全局变量和局部变量;env命令只显示全局变量,declare命令输出所有的变量、函数、整数和已经导出的变量。set -o命令显示bash shell的所有参数配置信息。
$ set -o|tail #<==tail输出输入文件的后10行
$ set -o|head #<==head输出输入文件的前10行
设置环境变量
如果要设置环境变量,就要在给变量赋值之后活在设置变量时使用export命令。(带-x选项的declare内置命令也可以完成同样的功能)。
export和declare命令的格式如下:
1.export 变量名=value
2.变量名=value ; export 变量名
3.declare -x 变量名=value
下面是自定义全局环境变量的示例:
$ grep OLD /etc/profile
$ export OLDBOY='oldboy' #<==编辑/etc/profile,然后输出并保存
$ source /etc/profile #<==执行使其生效
$ echo $OLDBOY
oldboy
$ env|grep OLDBOY #<==查看定义结果
OLDBOY=oldboy
下面来看看让环境变量永久生效的常用设置文件。
1)用户的环境变量配置
配置如下:
$ ls /root/.bashrc #<==一定要在root权限下执行
/root/.bashrc
$ ls /root/.bashrc_profile #<==在ubuntu中没有.bashrc_profile文件,有.profile文件
/root/.bashrc_profile
2)全局环境变量的配置
常见的全局环境变量的配置文件如下:
/etc/profile
/etc/bashrc #<==推荐在此文件中优先设置
/etc/profile.d/
若要在登录后初始化或显示加载内容,则把脚本文件放在/etc/profile.d/下即可(无需加执行权限)。
(2)设置登录提示的两种方式
第一种是在/etc/motd里增加提示的字符串,如下:
$cat /etc/motd
welcome to linux shell training.
则登陆后显示内容如下:
Last login : Fri Nov 7 15 :36 : 56 2017 from 10.0.0.100
welcome to linux shell training
第二种是在/etc/profile.d/下面增加如下脚本:
$ cat /etc/profile.d/oldboy.sh
echo "Here is a oldboy training"
登陆后显示的内容如下:
Last login : Fri Nov 7 15 :36 : 56 2017 from 10.0.0.100
Here is a oldboy training
以下是在生产场景下(在Java环境中),自定义环境变量的示例:
export JAVA_HOME=/application/jdk
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
export RESIN_HOME=/application/resin
上述的环境变量通常放在/etc/profile全局变量里。如果是写JAVA的脚本,那么最好是把上述Java环境配置放入脚本内重新定义,特别是作为定时任务执行的脚本。
显示与取消环境变量
1.通过echo或printf命令打印环境变量
常见的系统环境变量:
$HOME:用户登录时进入的目录
$UID:当前用户的UID(用户标识),相当于id-u
$PWD:当前工作目录的绝对路径名
$SHELL:当前shell
$USER:当前用户
在写shell脚本时可以直接使用系统默认的环境变量,一般情况下是不需要重新定义的,在使用定时任务等执行shell脚本时建议在脚本中重新定义。
2.用env或set显示默认的环境变量
3.用unset消除本地变量和环境变量
$ echo $USER
boyboy
$ unset USER
$ echo $USER
#<==此处为输出的空行,即消除了环境变量。
环境变量知识小结:
- 变量名通常要大写
- 变量可以在自身的shell及子shell中使用
- 常用export来定义环境变量
- 执行env默认可以显示所有的环境变量名称及其对应的值
- 输出时用“$变量名”,取消时用“unset变量名”
- 书写crond定时任务时要注意,脚本要用到的环境变量最好先在所执行的shell脚本中重新定义
- 如果希望环境变量永久生效,则可以将其放在用户环境变量文件或全局环境变量文件中。
环境变量初始化与对应文件的生效顺序
在登录Linux系统并启动一个bash shell时,默认情况下bash会在系统环境文件中查找环境变量的设置。bash检查的环境变量文件的情况取决于系统运行shell的方式。系统运行shell的方式一般有3种:
1)通过系统用户登录后默认运行的shell
2)非登录交互式运行shell
3)执行脚本运行非交互式shell
当用户登录Linux系统时,shell会作为登录shell启动。此时的登录shell加载环境变量的顺序。
[图片上传失败...(image-ceb883-1518419559984)]
- 首先加载/etc/profile全局环境变量文件,这是Linux系统上默认的shell主环境变量,系统上每个用户登录时都会加载这个文件
- 再执行/etc/profile.d目录下的脚本文件
- 然后运行$HOME/.bash_profile(用户环境变量文件),在这个文件中,又会去找$HOME/.bashrc(用户环境变量文件),如果有则执行,如果没有,则不执行。在$HOME/.bashrc文件中又会去找/etc/bashrc(全局环境变量文件),如果有则执行,如果没有则不执行。
- 如果用户的shell不是在登录时启动的,那么这种非登录Shell只会加载$HOME/.bashrc(用户环境变量文件),并会去找/etc/bashrc(全局环境变量文件)。
- 因此若希望在非登录shell下也可读到设置的环境变的内容,就需要将变量设定等写入$HOME/.bashrc
或者/etc/bashrc,而不是$HOME/.bash_profile或/etc/profile。
以上是在centos中的环境变量启动顺序,在ubuntu系统中:
- /etc/profile:在登录时操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息。当用户第一次登录时,该文件被执行。
- /etc/environment:在登录时操作系统使用的第二个文件,系统在读取你自己的profile前,设置环境文件的环境变量。
- /etc/bashrc:为每一个运行bash shell的用户执行此文件。当bash shell被打开时,该文件被读取。
- ~/.profile:在登录时用到的第三个文件是.profile文件,当用户登录时,该文件仅仅执行一次!默认情况下,执行用户目录下的.bashrc文件,每个用户都可使用该文件输入专用于自己使用的shell信息,修改后使用. .profile使生效。
- ~/.bashrc:该文件包含专用于单个用户的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取。修改后使用source .bashrc 使生效。
在ubuntu中设置环境变量:
通常设置环境变量有三种方法:
(一)临时设置
$PATH=/home/yan/share/usr/local/arm/3.4.1/bin:$PATH
(二)当前用户的全局设置
打开~/.bashrc,添加行:
export PATH=/home/yan/share/usr/local/arm/3.4.1/bin:$PATH
使生效:
source .bashrc
(三)所有用户的全局设置
$ vim /etc/profile
在里面加入:
export PATH=/home/yan/share/usr/local/arm/3.4.1/bin:$PATH
使生效
source profile
测试:
echo $PATH
十二、普通变量
定义本地变量
本地变量在用户当前shell生存期的脚本中使用。
- 普通变量定义
变量名=value
变量名='value'
变量名="value" - 在shell中定义变量名及为变量内容赋值的要求
变量名一般是由字母、数字、下划线组成的,可以以字母或下划线开头。变量的内容可以用单引号或双引号引起来,也可不加引号,但是三者的含义是不同的。 - 普通变量的定义及输出的示例
$ a=192.168.1.2
$ b='192.168.1.2'
$ c="192.168.1.2"
$ echo "a=$a"
a=192.168.1.2
$ echo "b=$b"
b=192.168.1.2
$ echo "c=${c}"
c=192.168.1.2
【$变量名表示输出变量,可以用$c和${c}两种用法】
将连续的普通字符串的内容赋值给变量,不管用不用引号,或者不管用什么用引号,它的内容是什么,打印变量时就会输出什么。
$ a=192.168.1.2-$a
$ b='192.168.1.2-$a'
$ c="192.168.1.2-$a"
$ echo "a=$a"
a=192.168.1.2-192.168.1.2
$ echo "b=$b"
b=192.168.1.2-$a
$ echo "c=${c}"
c=192.168.1.2-192.168.1.2-192.168.1.2
- 变量定义的基本技巧总结
a=192.168.1.2-$a
第一种a定义变量的方式是不加任何引号直接定义变量的内容,当内容为简单连续的数字、字符串、路径名时,
就可以这样用。不加引号时,值里有变量的会被解析后再输出。
b='192.168.1.2-$a'
第二种输出变量内容时单引号里是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们
原样输出。这种方式比较适合于定义显示纯字符串的情况,即不希望解析变量、命令等的情形。
c="192.168.1.2-$a"
第三种输出变量内容时引号里的变量及命令会经过解析再输出内容,而不是把双引号中的变量名及命令(命令
需要反引起来)原样输出。这种方式比较适合于字符串中附带有变量及命令且想将其解析后再输出的变量定义。
- 把一个变量的结果作为变量的内容赋值的方法
常见的方法有两种:
变量名=`ls` #<==把命令用反引号引起来
变量名=$(ls) #<==把命令用$()括起来,推荐使用这种方法
局部(普通)变量定义及赋值的小结
(1)常规普通变量定义
- 若变量内容为连续的数字或字符串,赋值时,变量内容两边可以不加引号,例如:a=123
- 变量的内容很多时,如果有空格且希望解析内容中的变量,就加双引号。
- 希望原样输出变量中的内容时就用单引号引起内容并进行赋值。
- 要使用反引号将赋值的命令括起来,例如a=
ls
;或者用$()括起来,例如:a=$(ls)。
(2)变量的输出方法如下: - 使用“$变量名”即可输出变量的内容,常用”echo$变量名“的方式,也可用printf代替echo输出更复杂的格式内容。
(3)变量定义的技巧及注意事项 - 注意命令变量内容前后的字符``(此字符是键盘上的tab键上面的那个反引号,不是单引号)。
- 在变量名前加$可以取得该变量的值,使用echo或printf命令可以显示变量的值。
- 用echo等命令输出变量的时候,也可用单引号、双引号、反引号。
- $dbname_tname,当变量后面连接有其他字符的时候,必须给变量加上大括号{},例如:$dbname_tname就要变成${dbname}_tname。这是shell就会认为只有dbname是变量了。
变量定义及变量输出说明
单引号、双引号、反引号与不加引号的知识说明表
名称 | 解释 | |
---|---|---|
单引号 | 所见即所得,即输出时会将单引号内的所有内容都原样输出,或者描述为单引号里面看到的是什么就会输出什么,这称为强引用 | |
双引号(默认) | 输出双引号内的所有内容;如果内容中有命令(要反引下)、变量、特殊转义符等,会先把变量 、命令、转义字符解析出结果,然后再输出最终的内容,推荐使用,这称为弱引用 | |
无引号 | 赋值时,若变量中有空格,则会造成赋值不完整。而在输出内容时,会将含有空格的字符串视为一个整体来输出;如果内容中有命令(要反引下)、变量等,则会先把变量、命令解析出结果,然后输出最终结果;如果字符串中带有空格等特殊字符,则有可能无法完整地输出,因此需要改加双引号。一般连续的字符串、数字、路径等可以不加任何引号进行赋值和输出,不过最好是用双引号替代无引号的情况,特别是对变量赋值时。 | |
反引号 | 一般用于引用命令,执行的时候命令会被执行,相当于$(),赋值和输出时都要用反引号将命令引起来 |
!这里仅为Linux shell 下的结论,对于awk语言会有点特别,有关awk调用shell变量的详情,请自行查询。不过,在awk取用shell变量时,我们更多地还是喜欢先用echo加符号输出变量,然后通过管道给awk,进而控制变量的输出结果。
建议:
- 在脚本中定义普通字符串变量时,应尽量把变量的内容用双引号括起来。
- 单纯数字的变量内容可以不加引号
- 希望变量的内容原样输出时需要加单引号
- 希望变量值引用命令并获取命令的结果时就用反引号或$()
变量定义技巧总结
(1)变量名及变量内容定义小结
- 变量名只能为字母、数字或下划线,只能以字母或下划线开头。
- 变量名的定义要有一定的规范,并且要见名知意。
- 一般的变量定义、赋值常用双引号;简单连续的字符串可以不加引号;希望原样输出时使用单引号。
- 希望变量的内容是命令的解析结果时,要用反引号,或者$()把命令括起来再赋值
(2)shell定义变量时使用“=”的知识 - “a=1”里等号是赋值的意思;比较变量是否相等时也可以用“=”或“==”。
(3)打印输出及使用变量的知识 - 打印输出或使用变量时,变量名前要接$符号;变量名后面紧接其他字符时,要用大括号将变量部分单独括起来;<span style="border-bottom:2px dashed red;">在unset、export、(())等场景中使用但不打印变量时不加$,这个有些例外。</span>
- 打印输出或使用变量时,一般加双引号或不加引号;如果是字符串变量,最好加双引号;希望原样输出时使用单引号。