一、什么是变量
在我们上学时,我们就接触数据方程式;例如:已知x=1 y=x+1 那么y等于多少,我们毫不犹豫的会算出来2,但是在shell中x就是变量名,那么对应的1就是变量值,在这里的等于号,在shell中称为赋值!
x=1 x(变量名) =(赋值) 1(变量值)
例如:以下在centos7中展示
[root@yankerp ~]# name="yankerp" <--定义变量-变量名为name,对应的变量值名字叫做yankerp [root@yankerp ~]# echo $name <--打印变量值使用echo $变量名 yankerp <--输出结果
以上例子就是一个自定义变量
变量赋值方式;先写变量名称,紧接着就是=号 =号的左右不可以有空格。最后是变量值,通过echo $(变量名) 就可以输出name变量的值,变量值一般需要加双引号。
二、变量的类型
变量可以分为两种类型:环境变量(全局变量) 普通变量(局部变量)
环境变量一般使用export内置命令导出的变量,用于定义shell运行环境,保证shell命令能够正确执行,shell通过环境变量来确定登录的用户名等信息,所有的环境变量都是系统的全局变量。
环境变量可以在命令行中创建,但是当用户退出命令行时这些变量将会丢失,如果需要永久保存环境变量,那么就可以在用户家目录下的.bash_profile 或者 .bashrc 按照系统的规范在设置环境变量时所有的环境变量名采用大写的方式;
例如:我现在要设置一个环境变量如下:
export UUU=yankerp 这种变量不会永久的保存!! 如果需要永久的保存上面已经说了在 .bashrc 或者 .bash_profile文件中设置
那么我们怎么看系统的变量呢? 使用set、env、declare命令查看,以下是env查看结果
XDG_SESSION_ID=171 HOSTNAME=yankerp TERM=xterm SHELL=/bin/bash HISTSIZE=3000 SSH_CLIENT=183.202.244.122 12158 22 SSH_TTY=/dev/pts/4 USER=root qq=aaaaaa LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36: MAIL=/var/spool/mail/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin PWD=/root LANG=en_US.utf8 SHLVL=1 HOME=/root LOGNAME=root SSH_CONNECTION=183.202.244.122 12158 10.141.58.170 22 LESSOPEN=||/usr/bin/lesspipe.sh %s PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" XDG_RUNTIME_DIR=/run/user/0 HISTTIMEFORMAT=%F %T _=/usr/bin/env
set env daclare的区别
set命令:输出全部的变量;
env命令:只输出全局变量;
declare命令:输出全部的变量、函数、整数和已经导出的变量;
set -o命令:显示bash shell的所有参数配置信息;
以下是set输出结果,使用tail查看set命令输出的最后5行等…
[root@yankerp ~]# set | tail -5 { local quoted; _quote_readline_by_ref "$1" ret; printf %s "$ret" }
[root@yankerp ~]# set -o | head -5 allexport off braceexpand on emacs on errexit off errtrace off
[root@yankerp ~]# env | tail -5 LESSOPEN=||/usr/bin/lesspipe.sh %s PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" XDG_RUNTIME_DIR=/run/user/0 HISTTIMEFORMAT=%F %T _=/usr/bin/env
三、自定义环境变量
1、设置环境变量
在设置环境变量之前我们需要使用export命令 具体如下:
export 变量名=tom export CSDN=yankerp
以下是自定义全局变量的实例
[root@yankerp ~]# tail -1 /etc/profile <----查看/etc/profile最后一行 export CSDN=yankerp ---<输出此行并保存 [root@yankerp ~]# source /etc/profile <---<使/etc/profile生效 [root@yankerp ~]# echo $CSDN <----在变量前面加上$符号并打印变量值 yankerp <----输出结果 [root@yankerp ~]# env | grep CSDN <----使用env查看环境变量并使用grep过滤CSDN变量值 CSDN=yankerp ----输出结果
2、修改登录提示
[root@yankerp ~]# cat /etc/motd this is a yankerp!!!
登录提示如下:
Last login: Sat Jan 27 23:27:01 2018 from this is a yankerp!!! [root@yankerp ~]#
3、用echo以及printf命令打印出环境变量
[root@yankerp ~]# echo $UID 0 [root@yankerp ~]# echo $USER root [root@yankerp ~]# echo $SHELL /bin/bash [root@yankerp ~]# printf "$HOME\n" /root
在以上的printf后面加\n是表示换行的意思,printf一般不是经常用,说白了这个命令是为awk打基础。
使用env或set命令显示默认的环境变量
[root@yankerp ~]# env MAIL=/var/spool/mail/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin CSDN=yankerp PWD=/root LANG=en_US.utf8 SHLVL=1 HOME=/root LOGNAME=root SSH_CONNECTION=183.202.244.122 12120 10.141.58.170 22 LESSOPEN=||/usr/bin/lesspipe.sh %s PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" XDG_RUNTIME_DIR=/run/user/0 HISTTIMEFORMAT=%F %T
用set命令显示环境变量包括局部变量
[root@yankerp ~]# set BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d BASH_LINENO=() BASH_SOURCE=() BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
问题来了 怎么取消变量呢?
例如:我设置一个环境变量
[root@yankerp ~]# export YANKAI=ywyankerp [root@yankerp ~]# echo $YANKAI ywyankerp [root@yankerp ~]# env | grep YANKAI YANKAI=ywyankerp
现在我们使用unset命令消除变量 如下:
[root@yankerp ~]# unset YANKAI [root@yankerp ~]# echo $YANKAI [root@yankerp ~]#
四、普通变量
1、定义本地变量
本地变量在用户当前的shell脚本中使用,如果在shell中开启另外一个进程或者说退出那么将会失效
普通变量的类型
变量名=yankerp 变量名='yankerp' 变量名="yankerp"
变量名一般都是由字母、数字、下划线组成的,变量名不能以数字开头
变量的内容可以用单引号、双引号、引起来,同时也可以不加引号,但是这三者的含义是不一样的。如下:
[root@yankerp ~]# a=192.168.1.10 [root@yankerp ~]# b='192.168.1.10' [root@yankerp ~]# c="192.168.1.10" [root@yankerp ~]# echo "a=$a" a=192.168.1.10 [root@yankerp ~]# echo "b=$b" b=192.168.1.10 [root@yankerp ~]# echo "c=$c" c=192.168.1.10 [root@yankerp ~]#
在以上例子中好像看不出来哪里不一样,说明了将连续普通的字符串的内容赋值给变量,不管用不用引号,只要变量名是什么,它就会打印什么
那么到这里到底有什么区别实例证明如下:
例如:我不用”引号设置变量和用”号设置如下:
[root@yankerp ~]# a=yan ker p -bash: ker: command not found [root@yankerp ~]# a='yan ker p' [root@yankerp ~]# echo $a yan ker p [root@yankerp ~]#
经过以上实例我们可以看到,不加单引号设置变量,其中变量名有空格,但是它会报错,如果我们加了单引号,其中变量名有空格,它就会打印出来我们设置的yan ker p;
结论:当我们不加单引号时必须是连续的字符串才可以;如果加了”号那么结论是当变量名写什么那么它就会输出什么。
“”号案例如下:
[root@yankerp ~]# a='yan ker p' [root@yankerp ~]# b="yan ker p" [root@yankerp ~]# echo $a yan ker p [root@yankerp ~]# echo $b yan ker p [root@yankerp ~]#
在以上的案例中我们并没有发现”号于“”号有什么区别,但是我们来继续看下面的案例
[root@yankerp ~]# a=$("ls") <----此变量名ls为linux命令 [root@yankerp ~]# echo $a anaconda-ks.cfg
总结:””这种定义的方式特点是:输出变量内容时引号变量及命令会经过解析后在输出
把一个变量命令赋值的方法
例如:我们要查询我们的IP地址 我们可以使用ifconfig这个命令来查看,但是我们如何在shell脚本中实现呢?
按照很普通的想法是这样的如下:
在以上脚本中我们就会认为,IP是变量名,ifconfig是变量值,那么我们执行这个脚本echo $IP 那么就会输出ip信息吗?
[root@yankerp Log.sh]# cat test1.sh #!/bin/bash # Sat Jan 27 20:45:40 CST 2018 # User <ywyankerp@163.com> # Version 1.1.0 # This is a cs. IP=ifconfig [root@yankerp Log.sh]# source test1.sh [root@yankerp Log.sh]# echo $IP ifconfig [root@yankerp Log.sh]#
我们发现它输出的是ifconfig字符串,为啥? 因为IP=ifconfig在linux中它会很简单的认为ifconfig就是个字符串并不是命令….
接下来介绍两个符号
变量名=`ifconfig` 变量名=$("ifconfig")
我们在上面已经说过””的作用,它是输出变量内容时引号变量及命令会经过解析后在输出
脚本内容如下:
[root@yankerp Log.sh]# cat test1.sh #!/bin/bash # Sat Jan 27 20:45:40 CST 2018 # User <ywyankerp@163.com> # Version 1.1.0 # This is a cs. IP=$("ifconfig") [root@yankerp Log.sh]# source test1.sh [root@yankerp Log.sh]# echo $IP eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.141.58.170 netmask 255.255.192.0 broadcast 10.141.63.255 ether 52:54:00:b3:c1:34 txqueuelen 1000 (Ethernet) RX packets 92758 bytes 9588691 (9.1 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 91995 bytes 12612699 (12.0 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
从以上脚本中我们可以看到ifconfig命令已经生效,我们暂时不用管他的排版
同时我们也可以在命令段的前后加“反撇号 这个看个人习惯 我是习惯用反撇号;
[root@yankerp ~]# IP=`ifconfig`
举几个例子“
[root@yankerp ~]# SJ=`date +%F`.tar.gz [root@yankerp ~]# echo $SJ 2018-01-28.tar.gz
以上date +%f就是一条命令 在这条命令的基础上我们加了“反撇号让它解析同时在后面加了.tar.gz 输出结果为时间+.tar.gz
再次测试如下:
[root@yankerp ~]# YYY=etc_`hostname`.tar.gz [root@yankerp ~]# echo $YYY etc_yankerp.tar.gz
[root@yankerp ~]# echo 'yankerp date +%F' yankerp date +%F [root@yankerp ~]# echo "yankerp date +%F" yankerp date +%F [root@yankerp ~]# echo "yankerp `date +%F`" yankerp 2018-01-28
注意以上的反撇号
案例1:在正则表达式三剑客中grep命令过滤字符串给加引号
[root@yankerp Log.sh]# cat test <------文本内容如下: yankerp zhangsan lisi wangwu zhouliu zhouwu zhousi CSDN [root@yankerp Log.sh]# aaa=yankerp <----设置变量aaa=yankerp [root@yankerp Log.sh]# grep $aaa test yankerp [root@yankerp Log.sh]# grep '$aaa' test [root@yankerp Log.sh]# grep "$aaa" test yankerp [root@yankerp Log.sh]#
案例2:在正则表达式三剑客中awk命令测试
[root@yankerp ~]# EEE=123456 [root@yankerp ~]# awk 'BEGIN {print "$EEE"}' $EEE [root@yankerp ~]# awk 'BEGIN {print '$EEE'}' 123456 [root@yankerp ~]# awk 'BEGIN {print "'$EEE'"}' 123456 [root@yankerp ~]#
我们发现和前面的不一样啊 不是说””是解析命令吗 为什么在awk中它是输入什么就输出什么呢,而使用”号在之前是输入什么就输出什么,这就是AWK调用shell变量的特殊用法