变量
变量名可以由字母、数字、下划线组成,但是不能以数字开头。在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/32768
、echo $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=11
、bb=22
、cc=$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的值。