今天给大家总结一下关于bash的颜色,配置文件,变量,数组和相关shell脚本编程的基本概念;
一.bash的颜色显示规则
吧是的颜色显示,说白了就是Ascll码对于颜色的调用设置,而在于颜色代码当中,字符串个功能实现如下:
\033:表示ctrl键;
[:控制字符和颜色代码之间的间隔字符;
0m:关闭颜色属性;
1m:加粗显示文本字符;
4m:为文本字符加下划线标识;
5m:使文本字符闪烁;
7m:将背景色和前景色调换,白变黑,黑变白;
8m:隐藏字符,将文本字符的背景色和前景色设置为相同颜色,同为黑或同为白;
30m-39m设置文本字符的前景色,即字体颜色,38m和39m暂时没有用到;
40m-49m:设置文本字符的背景色,即一个黑色字符的背景后是什么颜色,48m和49m暂时没有用到;
前景 背景 颜色
30m 40m 黑色
31m 41m 红色
32m 42m 绿色
33m 43m ×××
34m 44m 蓝色
35m 45m 紫红色
36m 46m 青蓝色
37m 47m 白色
例
加粗显示文本字符
[root@localhost wjq]# echo -e "\033[1mhello worl\033[0m"
hello worl
为文本字符加下划线标识
[root@localhost wjq]# echo -e "\033[4mhello worl\033[0m"
hello worl
加粗和设置下划线同时进行,利用“;”分隔;
[root@localhost wjq]# echo -e "\033[1;4mhello worl\033[0m"
hello worl
二.配置文件
一个完整的程序通常包含四类文件:
二进制文件:可执行文件;
头文件,库文件;
帮助文档;
配置文件;
所有在命令行进行命令的操作,只要没有设计到文件的修改都只是在当前生命周期有效的,当关闭系统后,再开启则无法使用;配置文件是实现数据永久显示的基本方法,将数据的改动放入配置文件中,当系统重启后还能重复调用,如修改alias别名放入配置文件bashrc的文本文档当中,bashrc就是一个配置文件;
配置文件分为私人配置文件与通用配置文件
通用配置文件:/etc/bashrc,/etc/profile
私人配置文件:~/.bashrc,~/.bash_profile
注意:一般情况下定义变量都是先做先用,并不需要改配置文件(声明变量在配置文件中可能使系统出现漏洞)没有必要就不要改;
配置文件又分为三类:
profile类:
为交互式登陆的shell进程实现功能初始化的配置文件;
bashrc类:
为非交互式登陆的shell进程实现功能启动配置的配置文件;
logout类:
为交互式登陆的shell进程提供终止及清理类功能的配置文件;
交互式登录:
1.通过某个终端输入账号密码来打开的shell进程;
2.通过su - username打开的shell进程;
非交互式登陆:
1.在图形界面,通过右键菜单打开终端的shell进程;
2.通过su username打开的shell进程;
profile类:
/etc/profile
/etc/profile.d/*.sh
全局:在上述路径中对配置文件进行修改,能对所有登陆的用户进行改变;
往往在profile文件中,如果一个配置文件中的内容过多,系统会把其切割成一个个片段,如profile.d,将切割出来的片段统
一的存放在”程序名称.d“目录,在该目录下有关于片段的所有文件大多以统一的文件名后缀来命名;
~/.bash_profile
局部:仅针对当前家目录的用户,对其进行改变,不影响其他用户;
bashrc类:
/etc/bashrc
全局:可以定义对系统全部用户有效的命令别名,本地变量,以及遮罩码umask;
~/.bashrc
局部:定义对于当前用户有效的命令别名,本地变量,以及遮罩码umask;
三.变量应用
1.字符串切片
${#var:}:返回变量var的字符串长度;
${var:offset}:返回字符串变量var的第offset个字符后面的字符串;
${var:offset:number}:返回字符串变量var的第offset个字符后面的number个字符;
例
[root@localhost wjq]# var="hello world"
[root@localhost wjq]# echo ${#var}
11
返回第六个字符后的字符串
[root@localhost wjq]# echo ${var:6}
world
返回第六个字符后的两个字符串
[root@localhost wjq]# echo ${var:6:2}
wo
2.基于模式取字串:根据不同方式取符合pattern的字符串
${var#*pattern}:在var字符串变量中,从左到右搜索第一个匹配字符串pattern的字符,删除从开始到第一个匹配到pattern的所有字符;
${var##*pattern}:在var字符串变量中,从左到右搜索最后一个匹配字符串pattern的字符,删除从开始到最后一个匹配到pattern的所有字符;
${var%pattern*}:在var字符串变量中,从右到左搜索第一个匹配到pattern的字符,删除从开始到从右到左匹配的第一个pattern之间的所有字符;
${var%%pattern*}:在var字符串变量中,从右到左搜索最后一个匹配到pattern的字符,删除从开始到从右到左最后一个匹配到的字符之间的所有字符;
例
①
[root@localhost wjq]# var=/etc/passwd
[root@localhost wjq]# echo ${var#*p}
asswd
②
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var##*/}"
passwd
③
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var%s*}"
/etc/pas
[wjq@localhost ~]$
④
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var%%s*}"
/etc/pa
[wjq@localhost ~]$
3.查找替换:利用不同方式,搜索字符串中匹配pattern的字符,并用substring字符串对其进行替换;
${var/pattern/substring}:在var字符串变量中,搜索第一个匹配到pattern的字符串,并用substring字符串对其进行替换;
${var//pattern/substring}:在var字符串变量中,搜索所有匹配到字符串pattern的字符串,并用substring字符串进行替换;
${var/#pattern/substring}:在var字符串变量中,搜索行首匹配到字符串pattern的字符串,并用substring字符串进行替换;
${var/%pattern/substring}:在var字符串变量中,搜索行尾匹配到字符串pattern的字符串,并用substring字符串进行替换;
例
①
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var/e/wu}"
/wutc/passwd
②
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var//s/wu}"
/etc/pawuwuwd
③
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var/#\//wu}"
wuetc/passwd
④
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var/%d/wu}"
/etc/passwwu
4.查找删除:利用不同方式,搜索匹配到的字符串并删除;
${var/pattern}:在字符串变量var中,将第一次匹配到pattern的字符串删除;
${var//pattern}:在字符串变量var中,将全部匹配到pattern的字符串删除;
${var/#pattern}:在字符串变量var中,将行首匹配到pattern的字符串删除;
${var/%pattern}:在字符串变量var中,将行尾匹配到pattern的字符串删除;
例
①
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var/p}"
/etc/asswd
②
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var//s}"
/etc/pawd
③
[wjq@localhost ~]$ echo "${var/#\/}"
etc/passwd
④
[wjq@localhost ~]$ echo "${var/%wd}"
/etc/pass
5.字符的大小写转换:
${var^^}:将字符串var变量中的所有小写字母转换成大写字母;
${var,,}:将字符串var变量中的所有大写字母转换成小写字母;
例
①
[wjq@localhost ~]$ var=/etc/passwd
[wjq@localhost ~]$ echo "${var^^}"
/ETC/PASSWD
[wjq@localhost ~]$
6.变量赋值:
${var:-value}:如果变量var为空或未被设置,那么直接返回value值,否则返回变量var值;
${var:+value}:如果变量var不为空,则返回value,为空则返回var;
${var:=value}:如果变量var为空或者未被设置,那么直接返回value值,并且将value值赋值给变量var,否则返回var值;
例
①
[wjq@localhost ~]$ var=//
[wjq@localhost ~]$ echo "${var:-qq}"
//
[wjq@localhost ~]$ var=
[wjq@localhost ~]$ echo "${var:-qq}"
②
[wjq@localhost ~]$ var=
[wjq@localhost ~]$ echo "${var:+qq}"
[wjq@localhost ~]$ var=a
[wjq@localhost ~]$ echo "${var:+qq}"
7.变量的间接引用:
如果第一个变量的值恰好是第二个变量的变量名,从第一个变量引用第二个变量的值的方法,就称为间接变量引用;
var1=var2
var2=value
bash提供了两种格式的间接变量引用方式:
eval myvar=\$$var1==>\$var2
myvar=$(!var1)
四.数组
数组:相当于几个变量的集合,存放着一个或多个内存空间;
在bash中只提供一维数组,并且没有限定数组大小,利用下标存取数组中的元素,数组元素由下标0开始编号即数组的索引结点:0,1,2...,数组可以采用连续的索引结点进行赋值——稠密数组,也可以采用不连续的索引结点进行赋值——稀疏数组。
数组名[下标]=值
例如:
$a[0]=beijing
$a[1]=hainan
$a[2]=shanghai
数组的声明:
1.数组可以采用上述声明方式逐个赋值
2.直接对数组元素进行赋值:
$a=("beijing" "shanghai" "tianjin")或者$a=([0]="beijing" [1]="shanghai" [3]="tianjin")
3.利用declare命令创建数组:
$declare -a 数组名
引用数组元素:
1.$name或${name},两者相同,若变量未定义则用空值替换;
2.引用固定的数组元素:${name[n]}引用索引结点为n的值;
3.引用整个数组的所有元素:${name[*]}或${name[@]}
例
[wjq@localhost ~]$ a[0]=beijing
[wjq@localhost ~]$ echo "${a[0]}"
beijing
[wjq@localhost ~]$ a=("wujunqi zhengzhong shaoning")
[wjq@localhost ~]$ echo "${a[0]} ${a[1]} ${a[2]}"
wujunqi zhengzhong shaoning
查看数组的长度:
可以通过${#name[*]}显示出这个数组有多少个有意义的元素;
例
[wjq@localhost ~]$ a=(wujunqi zhengzhong shaoning)
[wjq@localhost ~]$ echo "${#a[*]}"
3
数组切片:
${name:offset}:显示包括offset数字所表示的索引位置及以后的所有元素,去掉从第一个数组开始的offset个数组元素
${name:offset:number}:显示包括offset数字所表示的索引位置及包括offset个元素的number个元素;
如${name:3:2}:丢弃0-2的数组变量,只取3,4数组变量;
撤销数组:
unset array_name
删除数组中的元素:
unset array_name[index]
RANDOM变量:可以产生一组在0-32767之间的随机变量
例
[wjq@localhost ~]$ echo "$RANDOM"
16952
[wjq@localhost ~]$ echo "$RANDOM"
6653
五.bash脚本编程
shell脚本编程有三种:
过程式编程语言
脚本类编程语言
解释性语言
其中脚本类编程语言在实现功能时是通过调用外部文件来实现的;
过程式编程语言有三种结构,顺序执行结构,选择执行结构和循环分支结构;
1.顺序执行结构:
根据用户所写的脚本命令,从左至右,从上到下按顺序执行;
2.选择执行结构:
对于某特定语句,重复执行0次,一次或多次;如if,case语句;
if语句:
单分支语句:
if 测试条件
then 命令
fi
双分支语句:
if 测试条件
then 命令1
else 命令2
fi
多分支语句:
if 测试条件
then 命令1
elif 测试条件
then 命令2
。。。
fi
例
计算100以内所有整数的和;
#!/bin/bash
#
read -t 5 -p "Please input a integer[0]: " INTEGER
if [ -z $INTEGER ] ; then
INTEGER=0
fi
if ! echo $INTEGER | grep -q "^\<[[:digit:]]\+\>$" ; then
echo "You must input an integer."
exit 5
fi
case语句:
可以进行多重条件选择,相对于if,else的多分支语句,case语句的优势就在于节约了系统所消耗的资源,其语法格式为:
case 变量引用 in
模式1)
分支1
;;
模式2)
分支2
;;
...
*)
默认分支
;;
esac
其执行过程是,利用变量引用所代表的值分别与各类模式进行比较,如果发现变量引用的值与某一类模式相同时,就执行该模式字符串之后的各个命令,直到遇到两个分号结束为止;
case语句的模式可以匹配数字,字符串,通配符等模式;
注意:
①每个模式字符串后面可有一条或多条命令,最后一条命令必须要由“;;”隔开
②模式字符串可以使用通配符;
③如果一个模式字符串包含多个模式,则应用“|”隔开;
④各模式字符串应唯一;
⑤以关键字esac结束;
3.循环分支结构
将一段代码重复的执行0次,1次或多次;一个好的循环结构必须要包括两个最重要的环节,即进入循环的条件:开始循环时所满足的条件;
退出循环的条件:
循环结束所满足的条件;
shell中有三种用于循环的语句,即for,whie,until,select语句;
for语句:
for语句是最常用的循环结构语句。其使用方式主要有两种,一种是值表方式,另一种是算术表达式方式;for循环特点,几乎不会死循环,在执行循环的过程中,需要将这个LIST载入到内存当中;因此对于大列表来说可能会过多的消耗内存和cpu资源;
值表方式
其一般表达式为
for 变量 [in 值表];do 命令表;done
①值表可以是文件正则表达式,其格式为:
for 变量 in 文件正则表达式
do
命令表
done
其执行过程是,变量的值依次取当前目录下与正则表达式相匹配的文件名,每取值一次,就进入循环体执行命令表,直至所有文件名取完为止;
bash脚本编程之用户交互:
位置参数变量:$1,$2,$3,...
特殊变量:
$#:所有位置参数的总数;
$*:所有位置参数列表;当使用“”引用时,整个参数被当作一个字符串;
$@:所有位置参数列表;当使用“”引用时,每个参数作为单独的字符串存在;
$0:所执行脚本文件自身的路径;
②for循环脚本也可以是全部的位置参数$#与$*
for 变量 in $*
do
命令
done
③
for循环脚本可以直接使用纯整数列表
{1..100}:表明从1-100,中间只能为两点;
for i in {1..100}
do
命令
done
seq:输出一个整数列表
seq [OPTION]... FIRST INCREMENT LAST
seq 10:从1-10
seq 5 10:从5-10
for i in $(seq 10)
do
命令
done
在这里扩充一下关于read命令的功能
read 命令:从键盘上读取数据,然后赋给指定变量;
read [-a 数组] [-p 提示符] [-t 超时] []
利用read命令可交互的为变量赋值,输入数据时,数据间以空格或制表符作为分隔符;
①
变量个数与给定数据个数相同,则依次赋值
$read x y z
$today is sunny
$echo $x $y $z
today is sunny
②
变量个数少于数据个数,则从左至右赋值,但最后一个变量被赋予剩余的所有数;
③
变量个数多于数据个数,则依次对应赋值,而没有数据与之对应的变量取空串;
例
在脚本中-p选项给提示信息,相当于echo
$read -p "please enter" name
-t选项5秒钟内如果没有进行输入则返回,默认名字为link;
$read -t 5 -p "please enter[link]" name || [ -z $name] && name=link
算术表达式方式:
其一般格式为
for((表达式1; 表达式2; 表达式3 ))
do
命令表
done
表达式1:为变量赋初值;
表达式2:循环退出条件;
表达式3:变量值的变化规律;
如
for((T=1;I<=100;I++));do let "sum+=I";done;echo $sum
while语句:
格式:
①while 命令;do 命令;done
②while CONDITION;do
循环体
done
当CONDITION为真时,进入执行循环体中的语句,直至CONDITION为假时,跳出循环;
例当位置参数$1存在时执行while循环
while [ $1 ]
do
if [ -f $1 ]
then
echo "该文件为普通文本文件"
else
echo "$1 is not a file"
fi
done
until语句:
格式:
①until 命令;do 命令;done
②until CONDITION;do
循环体
done
当CONDITION为假时,进入执行循环体中的语句,直至CONDITION为真时,跳出循环;
循环控制命令:
continue语句:
跳出当前循环语句,回到本层循环的开头,进入下一轮条件判断,若符合条件则进入下一轮循环;
若处在多层嵌套循环中,如:
for
while
for
continue [3]
跳出到最外层的循环,进行最外层循环的下一轮条件判断,若符合则继续循环;
例如:
for i in 1 2 3
do
if [ $i -eq 2 ]
then
continue
fi
echo "$i"
done
break语句:
break语句可以使脚本从循环体中退出来,同continue相似,语法格式为:
break [n]
n默认值为1,即跳出一层循环;
若n=3时,表示连续跳出三层循环;
例如
for i in $*
do
if [ $i -eq 5 ]
then
break
else
echo "$i"
fi
done
当位置参数等于5时退出当前循环;
函数:
由某些功能封装在一起,在需要的时候可以直接调用,将这种封装起来的功能体称作为函数;
函数与shell程序在形式上是一致的,但是,shell程序是可以直接执行的,但函数中的语句是要通过函数调用过后才能被执行;此外,函数中的命令是在当前shell的环境中运行,而shell程序中的命令是在子shell环境中运行;
函数应先定义之后才能被执行,可以像普通命令一样直接使用,直接利用函数名,如show,不必带圆括号即可调用;shell脚本与函数之间可以进行参数传递,函数中的$1,$2所对应的值是函数在调用时所带的实参,还可以使用$*或$@的方式引用所有位置参数;还可以使用$#计算为函数传递的参数个数;这一点与普通命令不同;函数的生命周期是从被调用开始直到遇到return结束命令或全部的命令语句执行完为止;
如
show arg1 arg2
arg1和arg2作为函数的实参;
函数定义格式:
语法一:
函数名()
{
命令表
}
语法二:
function 函数名()
{
命令表
}
使用set命令可以查看所有当前shell中生效的函数;
使用unset命令可以撤销已经定义的函数;
调用函数之后函数的返回值有两种:
①函数结果的返回值
如echo,print等输出结果;
②函数状态返回值;
return [0];
函数的返回值不能用exit命令,n为退出函数时的退出值,即$?的值,n值默认时,则退出值是最后一个命令执行后的返回值;