一、正则表达式
1.1 基础正则表达式
1、正则表达式与通配符
- 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令可以支持正则表达式。
- 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
- 2、基础正则表达式
“ * ”前一个字符匹配0次,或任意多次
grep "a*" test_rule.txt
# 匹配所有内容,包括空白行,和正则表达式测试软件还是有些区别的。
grep "aa*" test_rule.txt
# 匹配至少包含有一个 a 的行
grep "aaa*" test_rule.txt
匹配最少包含两个连续a的字符串
grep "aaaaa*" test_rule.txt
#则会匹配最少包含四个个连续a的字符串
“ . ” 匹配除了换行符外任意一个字符
grep "s..d" test_rule.txt
# “ s..d ”会匹配在 s 和 d 这两个字母之间一定有两个字符的单词
grep "s.*d" test_rule.txt
# 匹配在 s 和 d 字母之间有任意字符
grep ".*" test_rule.txt
# 匹配所有内容
“ ^ ”匹配行首,“$”匹配行尾
grep "^M" test_rule.txt
# 匹配以大写“ M ”开头的行
grep "n$" test_rule.txt
# 匹配以小写“ n ”结尾的行
grep -n "^$" test_rule.txt
# 会匹配空白行
“ [ ] ” 匹配中括号中指定的任意一个字符,只匹配一个字符
grep "^[^a-z]" test_rule.txt
# 匹配不用小写字母开头的行
grep "^[^a-zA-Z]" test_rule.txt
# 匹配不用字母开头的行
“ \ ” 转义符
grep "\.$" test_rule.txt
# 匹配使用“ . ”结尾的行
“ {n} ”表示其前面的字符恰好出现n次(实际上为{ n },但在linux当中需要转义)
grep "a\{3\}" test_rule.txt
# 匹配 a 字母连续出现三次的字符串
grep "[0-9]\{3\}" test_rule.txt
# 匹配包含连续的三个数字的字符串
“ {n,} ”表示其前面的字符出现不小于n次
grep "^[0-9]\{3,\}[a-z]" test_rule.txt
# 匹配最少用连续三个数字开头的行
“{n,m}”匹配其前面的字符至少出现n次,最多出现m次
grep "sa\{1,3\}i" test_rule.txt
# 匹配在字母 s 和字母 i 之间有最少一个 a ,最多三个 a
二、字符截取命令
2.1 cut字段提取命令
[root@localhost ~]# cut [选项] 文件名
选项:
-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分割列
ps:grep获得符合条件的行。cut获得符合条件的列
[root@localhost ~]# vi student.txt
ID Name gender Mark #中间是TAB键形成的空白
1 Liming M 86
2 Sc M 90
3 Gao M 83
[root@localhost ~]# cut -f 2 student.txt
[root@localhost ~]# cut -f 2,3 student.txt
[root@localhost ~]# cut -d ":" -f 1,3 /etc/passwd # -d指定分隔符
cat /etc/passwd | grep "/bin/bash" | grep -v root | cut -d ":" -f 1
#可以得到除了root已经创建的用户名
cut命令的局限
[root@localhost ~]# df -h | cut -d " " -f 1,3
#中间以空格分割但是每个字段间的空格个数不同怎么办?awk可以解决,但很复杂。
2.2 printf命令
printf '输出类型输出格式' 输出内容
输出类型:
%ns: 输出字符串。n是数字指代输出几个字符
%ni: 输出整数。n是数字指代输出几个数字
%m.nf: 输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位
数,其中2位是小数,6位是整数。
输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是Backspace键
\f: 清除屏幕
\n: 换行
\r: 回车,也就是Enter键
\t: 水平输出退格键,也就是Tab键
\v: 垂直输出退格键,也就是Tab键
举几个例子
# ' '中包含的就是输出格式
[root@localhost ~]# printf %s 1 2 3 4
1234[root@localhost ~]# printf %s %s 1 2 3 4
%s1234[root@localhost ~]# printf '%s %s' 1 2 3 4
1 23 4[root@localhost ~]# printf '%s %s\n' 1 2 3 4
1 2
3 4
printf输出文件内容
printf '%s' $(cat student.txt)
#不调整输出格式
printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $(cat student.txt)
#调整格式输出
ps:printf输出文件内容不能直接跟文件名
在awk命令的输出中支持print和printf命令
- print:print会在每个输出之后自动加入一个换行符(Linux默认没有print命令)
- printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
2.3 awk命令
awk '条件1{动作1} 条件2{动作2}…' 文件名
条件(Pattern):
一般使用关系表达式作为条件
x > 10 判断变量 x是否大于10
x>=10 大于等于
x<=10 小于等于
动作(Action):
格式化输出
流程控制语句
[root@localhost ~]# vim testzz
id name gender mark
1 lm M 86
2 sc M 90
3 gao M 83
[root@localhost ~]# awk '{print $1 "\t" $3"\n"}' testzz
id gender
1 M
2 M
3 M
[root@localhost ~]# df -h | awk '{printf $2"\t"$4"\n"}'
容量 可用
16G 14G
341M 341M
353M 353M
353M 347M
353M 353M
8.0G 8.0G
1014M 880M
2.0G 1.8G
2.0G 2.0G
71M 71M
ps:awk读取数据也是先按行去读取,$0代表本行$1代表第一个字符串$2代表第二个字符串。
BEGIN的作用
[root@localhost ~]# awk 'BEGIN{print "this is a test begin"} {print $1 "\t" $3"\n"}' testzz
this is a test begin
id gender
1 M
2 M
3 M
END的作用
[root@localhost ~]# awk 'END{print "test end"} {print $1 "\t" $3 "\n"}' testzz
id gender
1 M
2 M
3 M
test end
FS可以指定分隔符
[root@localhost ~]# cat /etc/passwd | grep "/bin/bash"|awk '{FS=":"}{print $1"\t" $4}'
root:x:0:0:root:/root:/bin/bash
lingzhiling 1000
hsw 1001
bimm 1002
cangls 1003
st 1005
#因为是先读入数据再指定分隔符所以若不加BEGIN,会出现第一行没有分割的情况下
[root@localhost ~]# cat /etc/passwd | grep "/bin/bash"|awk 'BEGIN{FS=":"}{print $1"\t" $4}'
root 0
lingzhiling 1000
hsw 1001
bimm 1002
cangls 1003
st 1005
-F 分隔符也能达到同样的目的
[root@localhost ~]# cat /etc/passwd | grep "/bin/bash"|awk -F : '{print $1"\t" $4}'
root 0
lingzhiling 1000
hsw 1001
bimm 1002
cangls 1003
st 1005
关系运算符
[root@localhost ~]# vim testzz
id name gender mark
1 lm M 86
2 sc M 90
3 gao M 83
[root@localhost ~]# cat testzz |grep -v id | awk '$4>85 {print $2}'
lm
sc
2.4 sed命令
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。主要对命令结果的操作上。
[root@localhost ~]# sed [选项] ‘[动作]’ 文件名
选项:
-n: 一般sed命令会把所有数据都输出到屏幕 ,如果加入此选择,则
只会把经过sed命令处理的 行输出到屏幕。
-e: 允许对输入数据应用多条sed命令编辑
-i: 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
a \: 追加,在当前行后添加一行或多行。添加多行时,除最后 一行
外,每行末尾需要用“\”代表数据未完结。
c \: 行替换,用c后面的字符串替换原数据行,替换多行时,除最
后一行外,每行末尾需用“\”代表数据未完结。
i \: 插入,在当期行前插入一行或多行。插入多行时,除最后 一行
外,每行末尾需要用“\”代表数据未完结。
d: 删除,删除指定的行。
p: 打印,输出指定的行。
s: 字串替换,用一个字符串替换另外一个字符串。格式为“行范
围s/旧字串/新字串/g”(和vim中的替换格式类似) 。
举一些例子
[root@localhost ~]# vim testzz
id name gender mark
1 lm M 86
2 sc M 90
3 gao M 83
- 行数据操作
[root@localhost ~]# sed '2p' testzz
id name gender mark
1 lm M 86
1 lm M 86
2 sc M 90
3 gao M 83
#查看文件的第二行,会发现把所有数据都显示出来了
[root@localhost ~]# sed -n '2p' testzz
1 lm M 86
#只显示要搜索打的数据
[root@localhost ~]# sed '2,3d' testzz
id name gender mark
3 gao M 83
#删除2-3行的数据但不会修改文件本身
[root@localhost ~]# sed '2a hello' testzz
id name gender mark
1 lm M 86
hello
2 sc M 90
3 gao M 83
# 在第二行后追加 hello
[root@localhost ~]# sed '2a hello \ #注意回车才行
> world' testzz
id name gender mark
1 lm M 86
hello
world
2 sc M 90
3 gao M 83
# 在第二行前插入两行数据
[root@localhost ~]# sed '2c no such person' testzz
id name gender mark
no such person
2 sc M 90
3 gao M 83
# 数据行替换
- 字符串替换
#格式:sed ‘s/旧字串/新字串/g’ 文件名
[root@localhost ~]# sed '2s/lm/hao/g' testzz
id name gender mark
1 hao M 86
2 sc M 90
3 gao M 83
[root@localhost ~]# sed -e '2s/86/60/g;3s/90/100/g' testzz
id name gender mark
1 lm M 60
2 sc M 100
3 gao M 83**加粗样式**
#利用-e 进行多处修改;
三、字符处理命令
1、排序命令sort
[root@localhost ~]# sort [选项] 文件名
选项:
-f: 忽略大小写
-n: 以数值型进行排序,默认使用字符串型排序
-r: 反向排序
-t: 指定分隔符,默认是分隔符是制表符
-k n[,m]: 按照指定的字段范围排序。从第n字段开始,
m字段结束(默认到行尾)
例子
[root@localhost ~]# sort /etc/passwd
# 排序用户信息文件
[root@localhost ~]# sort -r /etc/passwd
# 反向排序
[root@localhost ~]# sort -t ":" -k 3,3 /etc/passwd
# 指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序,但是这是当成字符串排的,会发现有不符合原意的存在。
[root@localhost ~]# sort -n -t ":" -k 3,3 /etc/passwd
#用这个
2、统计命令wc
[root@localhost ~]# wc [选项] 文件名
选项:
-l: 只统计行数
-w: 只统计单词数
-m: 只统计字符数
条件判断
1、按照文件类型进行判断
两种判断格式
[root@localhost ~]# test -e /root/install.log
[root@localhost ~]# [ -e /root/install.log ] #注意有空格
[ -d /root ] && echo "yes" || echo "no"
# 第一个判断命令如果正确执行,则打印“ yes ”,否则打印“ no ”
2、按照文件权限进行判断
ps:权限是只要ugo其中一个有权限就会判断为真。
[ -w student.txt ] && echo "yes" || echo "no"
# 判断文件是拥有写权限的
3、两个文件之间进行比较
[root@localhost tmp]# ln abc bcd
#来个硬链接
[root@localhost tmp]# [ /tmp/abc -ef /tmp/bcd ] && echo yes ||echo no
yes
#inode相同输出yes
4、两个整数之间比较
举例子
[ 23 -ge 22 ] && echo "yes" || echo "no"
yes
# 判断 23 是否大于等于 22 ,当然是了
[ 23 -le 22 ] && echo "yes" || echo "no"
no
# 判断 23 是否小于等于 22 ,当然不是了
5、字符串的判断
例子
[root@localhost tmp]# name=hhh
# 给 name 变量赋值
[root@localhost tmp]# [ -z $name ] && echo yes || echo no
no
# 判断 name 变量是否为空,因为不为空,所以返回 no
aa=11
bb=22
# 给变量 aa 和变量 bb 赋值
[ "$aa" == "bb" ] && echo "yes" || echo "no"
no
# 判断两个变量的值是否相等,明显不相等,所以返回 no
6、多重条件判断
例子
aa=11
[ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no"
no
# 判断变量 aa 是否有值,同时判断变量 aa 的是否大于 23
# 因为变量 aa 的值不大于 23 ,所以虽然第一个判断值为真,
返回的结果也是假
五 流程控制
5.1 if语句
1、 单分支if条件语句
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
fi
单分支条件语句需要注意几个点
- if语句使用fi结尾,和一般语言使用大括号结尾不同
- [ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格
- then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了
2、双分支if条件语句
if [ 条件判断式 ]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
例子
#占用百分比判断
[root@localhost sh]# vim ducument.sh
#!/bin/bash
#Author hsw (qq:110)
result=$( df -h | grep "centos-root" | awk '{printf $5}' | cut -d "%" -f
1)
if [ $result -le 50 ]
then
echo "safe"
fi
[root@localhost sh]# ./ducument.sh
safe
例子1:备份mysql数据库
[root@localhost sh]# vim back-up
ntpdate asia.pool.ntp.org &> /dev/null
#同步系统时间
date=$(date +%y%m%d)
#把当前系统时间按照年月日格式赋予变量date
size=$(du -sh /usr/lib64/mysql)
#统计mysql数据库的大小,并把大小赋予size变量。
if [ -d /tmp/dbbak ]
then
echo "Date:$date" > /tmp/dbbak/info.txt
echo "Size:$size" >> /tmp/dbbak/info.txt
cd /tmp/dbbak
tar -zcPf bake-up-$date.tar.gz /usr/lib64/mysql /tmp/dbbak/info.txt & >/dev/null
else
mkdir /tmp/dbbak
echo "Date:$date" > /tmp/dbbak/info.txt
echo "Size:$size" >> /tmp/dbbak/info.txt
cd /tmp/dbbak
tar -zcPf bake-up-$date.tar.gz /usr/lib64/mysql /tmp/dbbak/info.txt & >/dev/null
fi
例子2:判断apache是否启动
#!/bin/bash
port=$(nmap -sT 192.168.43.200 | grep tcp | grep http | awk '{print$2}')
#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量port
if [ "$port" == "open" ]
then
echo “$(date) httpd is ok!” >> /tmp/autostart-acc.log
else
/etc/rc.d/init.d/httpd start &>/dev/null
echo "$(date) restart httpd !!" >> /tmp/autostart-err.log
fi
3、 多分支if条件语句
if [ 条件判断式1 ]
then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时,执行程序2
„省略更多条件 …
else
当所有条件都不成立时,最后执行此程序
fi
例子
[root@localhost sh]# vim elif
#!/bin/bash
#Author hsw
echo "please input a file name"
name=$1
if [ -z "$name" ]
then
echo "null,please input a not null"
exit 1
elif [ ! -e "$name" ]
then
echo "file is not exist"
exit 2
elif [ -f "$name" ]
then
echo "this is a file"
elif [ -d "$name" ]
then
echo "this is a directory"
else
echo "this is an other file"
fi
5.2 case语句
多分支case条件语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
例子
[root@localhost sh]# vim case
#!/bin/bash
#Author hsw
read -p "input your choose yes/no " -t 30 cho
case $cho in
"yes")
echo "Your chose is yes"
;;
"no")
echo "Your chose is no"
;;
*)
echo "Your chose is error"
;;
esac
5.3 for循环
语法一
for 变量 in 值1 值2 值3 ....
do
程序
done
例子
#注意这种格式的sao
cd /lamp
ls *.tar.gz > ls.log
for i in $ (cat ls.log)
do
tar -zxf $i &> /dev/null
done
rm -rf /lamp/ls.log
语法二
for((初始值;循环控制条件;变量变化))
do
程序
done
例子
[root@localhost sh]# vim sum
#!/bin/bash
sum=0
for(( i=1;i<101;i++ ))
do
sum=$(($sum+$i))
done
echo $sum
5.4 while循环与until循环
1、while循环
while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样了。
while [ 条件判断式 ]
do
程序
done
例子
[root@localhost sh]# vim sum
#!/bin/bash
#sum
#Author hsw
i=1
sum=0
while [ $i -le 100 ]
do
sum=$(($sum+$i ))
i=$(( $i+1 ))
done
echo "sum is $sum"
2、until循环
until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
until [ 条件判断式 ]
do
程序
done
例子
[root@localhost sh]# vim sum
#!/bin/bash
#sum
#Author hsw
i=1
sum=0
until [ $i -ge 101 ]
do
sum=$(($sum+$i ))
i=$(( $i+1 ))
done
echo "sum is $sum"