摘自:Oldboy Linux运维——SHELL编程实战
Shell变量:用一个固定的字符串(也可能是字符、数字等的组合)代替更多、更复杂的内容,该内容里可能还会包含变量、路径、字符串等其它的内容。
变量是暂时存储数据的地方及数据标记,所存储的数据存在于内存空间中,通过正确的调用内存空间中变量的名字就可以取出与变量对应的数据。
变量的内容一般要加双引号,以防止出错,特别是当值里的内容之间有空格时。
变量类型可分为两类:环境变量和普通变量。
环境变量也可称为全局变量,可以在创建它们的Shell及其派生出来的任意子进程Shell中使用,环境变量又可分为自定义环境变量和bash内置的环境变量。
普通变量也可称为局部变量,只能在创建它们的Shell函数或Shell脚本中使用。普通变量一般由开发者在开发脚本程序时创建。
环境变量
环境变量一般是指用export内置命令导出的变量,用于定义Shell的运行环境,保证Shell命令的正确执行。S和力量通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、Shell脚本和各类应用。
按照系统规范,所有环境变量的名字均采用大写形式。正确的环境变量定义方法为export OLDGIRL=1。
通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中。
在查看设置的变量时,有3个命令可以显示变量的值:set、env和declare(替代早期的typeset)。set命令输出所有的变量,包括全局变量和局部变量;env命令只显示全局变量;declare命令输出所有的变量、函数、整数和已经导出的变量。set -o命令显示bash Shell的所有参数配置信息。
如果想要设置环境变量,就要在给变量赋值之后或在设置变量时使用export命令,带-x选项的declare内置命令同样可以。格式如下:
export 变量名=value
变量名=value ; export 变量名
declare -x 变量名=value
对于用户的环境变量设置,比较常见的是用户家目录下的.bashrc和.bash_profile。
常用的全局环境变量的配置文件如下:
/etc/profile
/etc/bashrc
/etc/profile.d/
若要在登录后初始化或显示加载内容,则把脚本文件放在/etc/profile.d/下即可(无须加执行权限)。
设置登录提示的两种方式:
1. 在/etc/motd里增加提示的字符串,如下:
cat /etc/motd
Welcome to Vurtne.Lu Linux Shell training.
2. 在/etc/profile.d/下面增加如下脚本:
cat /etc/profile.d/Vurtne_Lu.sh
echo "Welcome to Vurtne.Lu Linux Shell training."
登录后显示的内容如下:
Welcome to Vurtne.Lu Linux Shell training.
书写crond定时任务时要注意,脚本要用到的环境变量最好先在所执行的Shell脚本中重新定义。
unset可以消除本地变量和环境变量。
登录shell:需要用户名、密码登录后才能进入的shell
非登录shell:不需要输入用户名和密码即可打开的Shell
执行exit命令,退出一个shell(登录或非登录shell);
执行logout命令,退出登录shell(不能退出非登录shell)。
登入shell加载启动脚本的顺序为:
/etc/profile → /etc/profile.d/ → .bash_profile → .bashrc → /etc/bashrc
非登入shell加载启动脚本的顺序:
.bashrc → /etc/bashrc → /etc/profile.d
普通变量
为普通变量的定义赋值,一般有以下3种写法:
变量名=value
变量名='value'
变量名="value"
变量名一般是由字母、数字、下划线组成的,可以以字母或下划线开头。
当变量后面连接有其它字符的时候,必须给变量加上大括号{},例如:$dbname_tname改成${dbname}_tname
变量定义的基本技巧总结:
① a=1+$a #输出为a=1+1
不加引号时,值里有变量的会被解析后再输出
② b='1+$a' #输出为b=1+$a
输出变量内容时单引号里是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。
③ c="1+$a" #输出为c=1+1+1
输出变量内容时引号里的变量及命令会经过解析后再输出内容,而不是把双引号中的变量名及命令(命令需要反引起来)原样输出。
数字内容的变量定义可以不加引号,其他没有特别要求的字符串等定义最好都加上双引号,如果真的需要原样输出就加单引号,定义变量加双引号是最常见的使用场景。
把一个命令的结果作为变量的内容赋值的方法:
变量名=`ls`
变量名=$(ls)
tar zcf etc_`date +%F`.tar.gz /etc #将时间作为压缩包名打包
tar zcf $(uname -n).tar.gz /etc/services #将主机名作为压缩包名打包文件
以下是单引号、双引号与不加引号的范例:
[root@yeebian ~]# echo 'today is date'
today is date
[root@yeebian ~]# echo 'today is `date`'
today is `date`
[root@yeebian ~]# echo "today is date"
today is date
[root@yeebian ~]# echo "today is `date`"
today is Wed May 24 10:20:54 EDT 2017
[root@yeebian ~]# echo "today is $(date)"
today is Wed May 24 10:21:11 EDT 2017
[root@yeebian ~]# echo today is $(date)
today is Wed May 24 10:21:20 EDT 2017
下面是awk调用Shell中的变量:
[root@yeebian ~]# ETT=123
[root@yeebian ~]# awk 'BEGIN {print "$ETT"}'
$ETT
[root@yeebian ~]# awk 'BEGIN {print $ETT}' [root@yeebian ~]# awk 'BEGIN {print '$ETT'}'
123
[root@yeebian ~]# awk 'BEGIN {print "'$ETT'"}'
123
[root@yeebian ~]# ETT='test'
[root@yeebian ~]# awk 'BEGIN {print "$ETT"}'
$ETT
[root@yeebian ~]# awk 'BEGIN {print $ETT}' [root@yeebian ~]# awk 'BEGIN {print '$ETT'}' [root@yeebian ~]# awk 'BEGIN {print "'$ETT'"}'
test
[root@yeebian ~]# ETT="ting"
[root@yeebian ~]# awk 'BEGIN {print "$ETT"}'
$ETT
[root@yeebian ~]# awk 'BEGIN {print $ETT}' [root@yeebian ~]# awk 'BEGIN {print '$ETT'}' [root@yeebian ~]# awk 'BEGIN {print "'$ETT'"}'
ting
[root@yeebian ~]# ETT=`pwd`
[root@yeebian ~]# echo $ETT
/root
[root@yeebian ~]# awk 'BEGIN {print "$ETT"}'
$ETT
[root@yeebian ~]# awk 'BEGIN {print $ETT}' [root@yeebian ~]# awk 'BEGIN {print '$ETT'}'
awk: BEGIN {print /root}
awk: ^ unterminated regexp
awk: cmd. line:1: BEGIN {print /root}
awk: cmd. line:1: ^ unexpected newline or end of string
[root@yeebian ~]# awk 'BEGIN {print "'$ETT'"}'
/root
通过上述几个例子显示:不管变量如何定义、赋值,除了家单引号以外,利用awk直接获取变量的输出,结果都是一样的,因此,在awk取用Shell变量时,我们更多得还是喜欢先用echo加符号输出变量,然后通过管道给awk,进而控制变量的输出结果。
[root@yeebian ~]# ETT="vurtne"
[root@yeebian ~]# echo "$ETT" | awk '{print $0}'
vurtne
[root@yeebian ~]# echo '$ETT' | awk '{print $0}'
$ETT
[root@yeebian ~]# echo $ETT | awk '{print $0}'
vurtne
[root@yeebian ~]# ETT=`pwd`
[root@yeebian ~]# echo "$ETT" | awk '{print $0}'
/root
[root@yeebian ~]# echo '$ETT' | awk '{print $0}'
$ETT
[root@yeebian ~]# echo $ETT | awk '{print $0}'
/root
三剑客grep、sed和awk:grep和sed都符合前面引号总结的规律,唯有awk比较特殊。
关于自定义变量字符串变量的建议:
1)内容是纯数字、简单的连续字符(内容中不带任何空格)时,定义时可以不加任何引号;
2)没有特殊情况时,字符串一律用双引号定义赋值,特别是多个字符串中间有空格时;
3)当变量里的内容需要原样输出时,需要用单引号(''),这样的需求极少。