跳到主要内容

12、Linux 教程:变量

变量

变量名可以由字母、数字、下划线组成,但是不能以数字开头。在bash中所有的变量默认都是字符串类型,如果要进行数值运算必须先转换类型。定义变量用等号连接,如abc=de等号两边不能有空格。定义时值有空格必须用引号括起来。

变量有几种:

名称 用途 使用限制
用户自定义变量(本地变量) 自定义 可以增加、可以修改定义
环境变量(一般大写) 操作系统环境相关 可以增加、可以修改定义
位置参数变量 向脚本中传递数据 不能增加、只能修改定义
预定义变量 bash中定义好的变量 不能增加、只能修改定义

位置参数变量本质上属于预定义变量。

查看变量的值可以执行set命令(对当前的shell的所有变量)。unset后加变量名可以删除变量。

执行echo $-可以列出所有set的设定值。

变量值的叠加

如果定义变量aa:aa=123然后再修改aa的值:aa="$aa"456,或aa=${aa}那么aa的值就会变成123456

叠加也可以用另一种形式aa=${aa}789,这样aa的值也会变成123789

变量的删除和替代

以path为例说明(将该值定义为PATH的值:path=${PATH}):

/usr/lib64/qt3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/module/jdk1.8.0_144/bin:/root/bin

1、删除第一个目录:echo ${path#/*/bin:},执行后结果:

/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/module/jdk1.8.0_144/bin:/root/bin

这里的#意思是从变量最前面开始向右删除,且仅删除匹配的内容最短的那个,/*/bin:是要删除的匹配内容,*代表任意多个字符的通配符。

2、只保留最后一个目录:echo ${path##/*:},执行后结果:

/root/bin

这里的##的意思是从变量最前面开始向右删除,且仅删除匹配内容最长的那个,/*:是要删除的匹配内容。

3、 删除最后一个目录:echo${path%:*/bin},这里的%代表从右向左删除,且删最短的内容;

4、 仅保留第一个目录:echo${path%%:*bin},这里%%代表从右向左删除,且删最长的内容;

对于一个变量road为/var/spool/mail/dmtsai,那么${road##/*/}为文件名dmtsai,而${road%/*}为路径/var/spool/mail,利用这些手段可以轻松取到路径的文件名和目录名。

5、 将变量内容中的第一个sbin取代成SBIN:echo${path/sbin/SBIN}

6、 将变量内容中的全部sbin取代成SBIN:echo${path//sbin/SBIN}

变量的测试和内容替换

用于变量的赋值情况依赖于另一个变量的值这种情况,或者一个变量需要测试是否为空字符串或不存在时:

 

上表中最左边为变量的设置方式,根据str的情况,决定变量var的值,expr是一个普通字符串,不用加引号。

等号=的作用是不仅能根据str改变var的值,还能改变str本身。

而?的作用是直接给出提示信息,如果str不存在或空字符串会直接打印错误信息。

这个功能其实可以用ifthen处理,但是它更简单快捷。

环境变量

环境变量不仅在当前shell生效,在其子shell中也生效,而本地变量只在当前shell中生效。如果把环境变量的定义写入配置文件,那么环境变量就会在所有shell中生效。所谓子shell就是在当前shell的情况下启用的另一个新shell,一般的变量无法在父shell中定义在子shell中使用,除非是环境变量。

如果执行csh就说明进入了csh,同理执行bash也是一样,都相当于默认bash开启了子shell(可以执行exit退出子shell)。可以通过查看进程树pstree命令来观察子shell和父shell:

 

环境变量定义格式export 变量名=变量值,还可以直接export后跟变量名直接把变量变为环境变量。查看所有环境变量的命令env,或者直接执行export也可以查看环境变量。删除变量还是用unset命令。环境变量中有几个很重要:

1、 PATH,它是用冒号分割的一个一个的路径,执行系统命令时linux会自动寻找命令在不在这些路径下,然后执行,对于同名指令,先找到的就执行,如果没有找到就会报错,用户可以在PATH中添加自己的路径,操作命令是PATH="$PATH":/root相当于把root路径加入了PATH中,但是这种修改是临时的,想要永久修改必须修改文件;

PATH=${PATH}:/home/bin和上一个命令的作用相同。

2、 PS1,他是定义系统提示符的变量;

3、 HOME,代表用户的家目录,这就是为什么cd~或cd可以回到家目录的原因;

4、 SHELL,当前环境使用的shell;

5、 HISTSIZE,历史命令记录的最大笔数;

6、 LANG(主语言的环境)和LC_ALL(整体语系的环境);

7、 RANDOM,随机数生成器,可以直接取$RANDOM来获得随机0-32767之间的数,如果想要取0-9的数值,就先用declare定义整形变量再取用:;

declare -i number=$RANDOM*10/32768echo $number

环境变量配置文件

source命令的作用是使修改后的配置文件立即生效:source 配置文件. 配置文件,后者是source的简化。

环境变量配置文件在登录时会按照一定的顺序加载:

 

如果是正常输入账号密码登录,就会按/etc/profile、/etc/profile.d/*.sh、/etc/profile.d/lang.sh、/etc/sysc.config/i18n、/.bash_profile、/.bashrc、/etc/bashrc来加载配置文件,如果是非正常登录(bash切换子shell),就会按照/etc/bashrc、。。。/etc/sysc.config/i18n来加载配置文件。这些配置文件都可以写入环境变量的定义,越靠后优先级最大,目录以~为首的配置文件只会在特定用户生效,其他文件中的环境变量定义对所有用户都生效。

在CentOS7中,用户登录时会加载系统整体设定文件/etc/profie以及使用者个人设定文件~/.bash_profile。

/etc/profie文件定义了一些重要的环境变量,它还会呼叫外部的设定数据,如/etc/profile.d/*.sh(定义各种别名、bash操作结口的颜色)、/etc/locale.conf(语系配置文件)、/usr/share/bash-completion/completions/*(命令补齐和文档补齐相关设置)。

当读完了整体设定文件后会加载使用者的个人配置文件/.bash_profile,如果该文件不存在就加载/.bash_login文件,如果还不存在就加载/.profile,之所以PATH路径中有家目录下的bin目录,就是因为/.bash_profile做了用户个性化处理。

在CentOS7的non-login shell(su切换用户、子shell等)情况下只会加载~/.bashrc,它会呼叫/etc/bashrc(设置umask和PS1)和/etc/profile.d/*.sh。

注销时生效的环境变量配置文件,记录了注销后系统的动作:~/.bash_logout

记录历史命令的配置文件:~/bash_history

记录man命令的查看数据路径:/etc/man_db.conf

位置变量参数

基本格式是$n,$0代表命令本身,$1-$9代表第1-9个参数,十以上的参数需要用大括号包含,如${10}

#!/bin/bash

num1=$0
num2=$1
num3=$2
sum1=$(($num2+$num3))  
sum2=$(($3+$4))

echo $num1
echo $sum1
echo $sum2

脚本中如果涉及运算那么必须用双括号括起来。

运行脚本时后面加参数,运行结果:

 

$*代表所有参数,它把所有参数看成一个整体。$@也代表所有参数,它把每个参数区别对待。

两者的区别可以通过运行以下脚本得出:

#!/bin/bash

for i in "$*"
	do
		echo $i
	done
	
for j in "$@"
	do
		echo $j
	done

其中for i in "$*"的意思是获取所有参数然后进行循环,每次循环前将参数赋值给i,循环次数取决于参数个数。

运行结果:

 

$#代表命令行执行时的参数个数。

预定义变量

几个重要的预定义变量:

1、 $,它代表当前shell的线程号,查看当前shell线程号:echo$$

2、 ?,它代表上一个执行的指令所回传的值;

$?代表上一次命令的执行状态,0代表执行成功,非0代表执行不成功,具体的值由命令的制作者来决定。查看上一个命令的执行情况:echo $?,&&和||都是通过检查$?的值来确定多命令怎样执行。

3、 !,$!表示后台运行的最后一个进程的PID;

接受键盘输入

接受键盘输入的基本格式是read [选项] [变量名],-t后跟数字代表等待用户输入的时间,单位是秒;-s是隐藏输入的数据,数据输入后在屏幕上没有显示;-p是显示提示信息,后接提示信息;-n是read命令接受的字符数,接受够了就会执行该命令。

#!/bin/bash

read -t 30 -p "Please input your name: " name
echo "Name is $name "

read -s -t 30 -p "Please enter your age: " age
echo -e "\n"
echo "Age is $age "

read -n 1 -t 30 -p "Please select your gender[M/F]: " gender
echo -e "\n"
echo "Sex is $gender"

执行上述脚本:

 

数值运算与运算符

如果执行aa=11bb=22cc=$aa+$bb则cc的值不是33,而是11+22。

声明变量类型命令declare [+/-] [选项] 变量名,+代表取消变量的类型属性,-代表设置变量的类型属性,-i代表将变量声明为整数型,-x代表将变量声明为环境变量,-p表示显示指定变量的声明类型,-a代表声明变量为数组类型,-r代表声明变量为只读类型。如果在bash中不指定变量类型,那么就默认为字符串。

如果直接用declare查看aa的声明类型,结果显示没有类型,如果声明为环境变量再查看,则可以看到类型为x:

 

取消sum的环境变量属性:declare +x sum

不要轻易设置变量为只读,一旦设置了就必须再次登入才能恢复。

如果声明了var为数组变量,那么用这样的方式填入数据:var[1]=ali,读取时直接表示为${var}(注意数组的第一个值索引值是1)

实现数值运算的方法有三种:

1、 声明变量为整形:declare-icc=$aa+$bb

2、 expr数值运算工具:dd=$(expr$aa+$bb)(注意加号两边都要有空格);

3、 $((运算式))或$[运算式],如ff=$(($aa+$bb))或gg=$[$aa+$bb]($()代表调用系统命令,$(())代表运算);

bash环境中的数值运算,预设最多仅能到达整数形态,如果想计算含有小数点的数据的话,可以通过bc命令的协助,如执行:echo "123.123*55.9" | bc,bc命令还可以用来计算π,如:

echo "scale=${num};4*a(1)" | bc -lq,4*a(1)就是计算π的函数,而scale是计算的小数点下位数,scale设置的越高计算时间越长,大于5000就会很长,这个命令常常用来使CPU处于忙碌状态。

变量测试和内容替换

不同的变量置换方式如下表,前4行表达式的含义是当y的情况不同,x的赋值情况也不同,相当于根据y的各种情况决定x的值。后4行表达式根据y的各种情况不仅改变x的值,也改变y的值。