正则表达式和通配符的区别:
元字符 | 作用 |
---|---|
* | 前一个字符匹配0次或者任意多次 |
. | 匹配除了换行符外任意一个字符 |
^ | 匹配行首,例如:^hello会匹配以hello开头的行。 |
$ | 匹配行首,例如:hello$会匹配以hello开头的行。 |
[ ] | 匹配括号中指定的任意一个字符,只匹配一个字符 |
[ ^] | 匹配除中括号的字符意外的任意一个字符。例如:[^0-9]匹配任意一个非数字字符。 |
\ | 转义符。用于将特殊符号的含义取消 |
{n} | 表示其前面的字符签好出现n次。例如:[0-9]{4}匹配4位数字,[1][3-8][0-9]{9} 匹配手机号码 |
{n,} | 表示七千亩的字符出现不小于n次。例如:[0-9]{2,}表示两位及以上的数字 |
{n,m} | 表示其前面的字符至少出现n次,最多出现m次。例如:[a-z]{6,8}匹配6到8为的小写子母。 |
范例:
grep "a*" test_rule.txt
#匹配所有内容,包括空白行
grep "aaaa*" test_rule.txt
#匹配最少包含三个连续a的字符串
grep "s..d" test_rule.txt
#匹配在s和d两个子母之间的有两个字符的单词
grep "s.*d" test_rule.txt
#匹配在s和d之间有任意字符的单词所在的行
grep "^M" test_rule.txt
#匹配以大写子母M开头的行
grep "n$" test_rule.txt
#匹配以小写n结尾的行
grep -n "^$" test_rule.txt
#匹配空白行
grep "^[a-z]" test_rule.txt
#匹配以小写子母开头的行
grep "\.$" test_rule.txt
#匹配以.结尾的行
cut
语法:
cut [选项] [文件名]
-f 指定选取的列,多列以“,”隔开
-d 指定分隔符
**局限:**不能很好截取以多个空格作为分隔符的行。
[root@mysql sh]# cat student.txt
ID Name Gender Score
1 liming M 88
2 liuwei M 66
#提取第二、三列数据
[root@mysql sh]# cut -f 2,3 student.txt
Name Gender
liming M
liuwei M
#指定分隔符为“:”
[root@mysql sh]# cut -d ":" -f 2,3 /etc/passwd
x:0
x:1
x:2
x:3
x:4
printf
语法:
printf '输出类型输出格式' 输出内容
%ns: 输出字符串。n是数字指代输出几个字符
%ni: 输出整数。n是数字指代输出几个数字
%m.nf:输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表输出8位数,其中2位是小数,6位是整数。
常用输出格式:
\n: 换行
\r: 回车
\t:水平输出退格键,也就是Tab键
范例:
[root@mysql sh]# printf '%s %s %s\n' 1 2 3 4 5 6
1 2 3
4 5 6
awk
语法:
awk '条件1 {动作1} 条件2 {动作2} ……' 文件名
条件(Pattern):
一般使用关系表达式作为条件
- x>10 判断变量x是否大于10
- x>=10 大于等于
- x<= 小于等于
动作(Action)
范例:
以多个空格为分隔符的列表
[root@mysql ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 28G 4.3G 24G 16% /
devtmpfs 979M 0 979M 0% /dev
tmpfs 991M 0 991M 0% /dev/shm
tmpfs 991M 9.5M 981M 1% /run
tmpfs 991M 0 991M 0% /sys/fs/cgroup
/dev/sda1 497M 126M 372M 26% /boot
tmpfs 199M 0 199M 0% /run/user/0
awk
命令中“printf
”命令不会自动换行,“print
”命令可以自动换行。
[root@mysql ~]# df -h | awk '{printf $1 "\t" $5 "\t" $6 "\t\n"}'
Filesystem Use% Mounted
/dev/mapper/rhel-root 16% /
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 1% /run
tmpfs 0% /sys/fs/cgroup
/dev/sda1 26% /boot
tmpfs 0% /run/user/0
[root@mysql ~]# df -h | awk '{print $1 "\t" $3}'
Filesystem Used
/dev/mapper/rhel-root 4.3G
devtmpfs 0
tmpfs 0
tmpfs 9.6M
tmpfs 0
/dev/sda1 126M
tmpfs 0
[root@mysql ~]# df -h |grep sda1
/dev/sda1 497M 126M 372M 26% /boot
[root@mysql ~]# df -h |grep sda1 | awk '{printf $5}'
26%[root@mysql ~]# df -h |grep sda1 | awk '{printf $5 "\n"}'
26%
[root@mysql ~]# df -h |grep sda1 | awk '{printf $5 "\n"}' | cut -d "%" -f 1
26
BEGIN
命令:先执行期望打印内容之前的命令。
[root@mysql sh]# awk 'BEGIN {print "test!"} {print $2 "\t" $3}' student.txt
test!
Name Gender
liming M
liuwei M
FS内置变量
awk命令默认分割符为“空格”以及“制表符”,无法自动识别“:”
[root@mysql sh]# awk '{print $1 "\t" $3}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
awk 命令会先读取后处理,因此第一行数据没有分割
[root@mysql sh]# awk '{FS=":"} {print $1 "\t" $3}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
添加BEGIN
命令强制先处理
[root@mysql sh]# awk 'BEGIN{FS=":"} {print $1 "\t" $3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
END
命令
[root@mysql sh]# awk 'END{print "The end"} {print $2 "\t" $3}' student.txt student.txt
Name Gender
liming M
liuwei M
The end
关系运算符 :每行的数据先判断才会执行打印命令
[root@mysql sh]# cat student.txt |grep -v Name | awk '$4>=85 {print $2}'
liming
sed命令
sed是一种几乎包括在所以UNIX平台的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
语法:
[root@localhost ~]# sed [选项] '[动作]' 文件名
选项:
-n 一般sed命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过Sed命令处理的行输出到屏幕。
-e: 允许对输入数据应用多条sed命令编辑
-i: 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
a \: (append)追加,在当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾用“\”代表数据未完结。
c \: (change)行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。
i \: (insert)插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用“\”代表数据未完结
d: (delete)删除,删除指定的行
p: (print)打印,输出指定的行
s: (substitute)字串替换。用一个字符串替换另外一个字符串。格式为“行范围s/旧字符/新字符/g” (和vim中的替换格式类似)
范例:
不加“-n“的话,除了输出第二行,所有数据都会输出一遍
[root@mysql sh]# sed '2p' student.txt
ID Name Gender Score
1 liming M 88
1 liming M 88
2 liuwei M 66
[root@mysql sh]# sed -n '2p' student.txt
1 liming M 88
sed命令可以对命令输出结果直接进行处理,vi命令只能处理文件
[root@mysql sh]# df -h | sed -n '2p'
/dev/mapper/rhel-root 28G 4.3G 24G 16% /
删除行,没有修改文件本身的内容,只是对输出进行了处理
[root@mysql sh]# sed '2,3d' student.txt
ID Name Gender Score
3 zhao M 90
插入行
[root@mysql sh]# sed '4i hello' student.txt
ID Name Gender Score
1 liming M 88
2 liuwei M 66
hello
3 zhao M 90
[root@mysql sh]# sed '3a hello \ world' student.txt #”\“表示没输入完
ID Name Gender Score
1 liming M 88
2 liuwei M 66
hello world
3 zhao M 90
行替换
[root@mysql sh]# sed '4c no such person' student.txt
ID Name Gender Score
1 liming M 88
2 liuwei M 66
no such person
字符串替换
[root@mysql sh]# sed '4s/90/95/g' student.txt
ID Name Gender Score
1 liming M 88
2 liuwei M 66
3 zhao M 95
sort
格式:
[root@localhost ~]# sort [选项] 文件名
-f 忽略大小写
-n 以数值型进行排序,默认使用字符串型排序
-r 反向排序
-t 指定分隔符,默认是分隔符是制表符
-k n[,m]: 按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)
范例:
根据用户的”uid“(第三个字段)进行排序
[root@mysql sh]# sort -n -t ":" -k 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
wc
格式:
[root@localhost ~]# wc [选项] 文件名
-l: 只统计行数
-w: 只统计单词数
-m: 只统计字符数
范例:
[root@mysql sh]# wc /etc/passwd
20 28 876 /etc/passwd
# 20行 28个单词 876个字符
测试一个条件是否成立,常用的选项有三个
测试选项 | 作用 |
---|---|
-b 文件 | 判断该文件受否存在,并且是否为块设备文件(是块设备文件为真) |
-c 文件 | 判断该文件受否存在,并且是否为字符设备文件(是字符设备文件为真) |
-d 文件 | 判断该文件受否存在,并且是否为目录文件(是目录文件为真) |
-e 文件 | 判断该文件受否存在(存在为真) |
-f 文件 | 判断该文件受否存在,并且是否为普通文件(是普通文件为真) |
-L 文件 | 判断该文件受否存在,并且是否为符号链接文件(是符号链接文件为真) |
-p 文件 | 判断该文件受否存在,并且是否为管道文件(是管道文件为真) |
-s 文件 | 判断该文件受否存在,并且是否为非空(非空为真) |
-S 文件 | 判断该文件受否存在,并且是否为套接字(是套接字文件为真) |
两只判别格式范例:
[root@mysql sh]# test -e student.txt
[root@mysql sh]# echo $? #查看上一条命令是否执行正确
0
[root@mysql sh]# [ -e student.txt ]
[root@mysql sh]# echo $?
0
#第一条判断命令如果正确执行,打印”yes",否则打印”no“
[root@mysql sh]# [ -e studnt.txt ] && echo "Yes" ||echo "No"
No
[root@mysql sh]# [ -e student.txt ] && echo "Yes"||echo "No"
Yes
测试选项 | 作用 |
---|---|
-r 文件 | 判断该文件受否存在,并且是否该文件有读权限(有读权限为真) |
-w 文件 | 判断该文件受否存在,并且是否该文件有写权限(有写权限为真) |
-x 文件 | 判断该文件受否存在,并且是否该文件执行权限(有执行权限为真) |
-u 文件 | 判断该文件受否存在,并且是否该文件有SUID权限(有SUID权限为真) |
-g 文件 | 判断该文件受否存在,并且是否该文件有SGID权限(有SGID权限为真) |
-k 文件 | 判断该文件受否存在,并且是否该文件有SBit权限(有SBit权限为真) |
范例:
[root@mysql sh]# [ -w student.txt ] && echo "yes" ||echo "no"
yes
测试选项 | 作用 |
---|---|
文件1 -nt 文件2 |
判断文件1的修改时间是否比文件2的新(如果新则为真)newer than |
文件1 -ot 文件2 |
判断文件1的修改时间是否比文件2的旧(如果旧则为真) older than |
文件1 -ef 文件2 |
判断文件1是否和文件2的Inode号(i节点)一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接 equal file |
范例:
ln /tmp/sh/student.txt /tmp/stu.txt #创建硬链接
[root@mysql sh]# [ /tmp/stu.txt -ef /tmp/sh/student.txt ] && echo "yes" || echo "no"
yes
[root@mysql sh]# ls -i /tmp/stu.txt #查看文件i节点
17187280 /tmp/stu.txt
[root@mysql sh]# ls -i /tmp/sh/student.txt
17187280 /tmp/sh/student.txt
测试选项 | 作用 |
---|---|
整数1 -eq 整数2 | 判断整数1是否和整数2相等(相等为真)equal |
整数1 -ne 整数2 | 判断整数1是否和整数2不相等(不相等为真)not equal |
文件1 -gt 文件2 | 判断整数1是否大于整数2(大于为真) |
文件1 -lt 文件2 | 判断整数1是否小于整数2(小于为真) |
文件1 -ge 文件2 | 判断整数1是否大于等于整数2(大于等于为真) |
文件1 -le 文件2 | 判断整数1是否小于等于整数2(小于等于为真) |
范例:
[root@mysql sh]# [ 23 -le 30 ] && echo "yes" || echo "no"
yes
测试选项 | 作用 |
---|---|
-e 字符串 | 判断字符串是否为空(为空返回真) |
-n 字符串 | 判断字符串是否为非空(非空返回真) |
字符串1 == 字符串2 | 判断字符串1是否和字符串2相等(相等返回真) |
字符串1 != 字符串2 | 判断字符串1是否和字符串2不相等(不相等返回真) |
范例:
[root@mysql sh]# [ -z "$name" ] && echo "yes" || echo "no"
no
[root@mysql sh]# [ "$aa" == "$bb" ] && echo "yes" || echo "no" ##”==“两边要加空格否则全判断为真
no
测试选项 | 作用 |
---|---|
判断1 -a 判断2 | 逻辑与,判断1和判断2都成立,最终的结果才为真 |
判断1 -o 判断2 | 逻辑或,判断1和判断2有一个成立,最终的结果才为真 |
! 判断 | 逻辑非,使原始的判断式取反 |
if
语句单分支if 语句格式:
if [ 条件判断式 ] ; then
程序
fi
或者
if [条件判断式]
then
程序
fi
判断分区使用率范例:
#脚本内容
[root@mysql ~]# more /tmp/sh/if_test.sh
#!/bin/bash
#统计根分区使用率
rate=$(df -h | grep "/dev/sda1" | awk '{print $5}' | cut -d "%" -f1)
#把根分区使用率作为变量值赋给rete
if [ $rate -le 80 ]
then
echo "$rate" "Warning /dev/sda3 isn't full!!"
#脚本运行结果
[root@mysql ~]# /tmp/sh/if_test.sh
26 Warning /dev/sda3 isn't full!!
双分支if语句格式:
if [ 条件判断式 ]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
备份范例:
[root@mysql sh]# cat -n if_test2.sh
1 #!/bin/bash
2
3 date=$(date +%y%m%d)
4 size=$(du -sh /tmp)
5
6 if [ -d /tmp/dbback ]
7 then
8 echo "Date is : $date" > /tmp/dbback/db.txt
9 echo "Size is : $size" >> /tmp/dbback/db.txt
10 tar -zcf tmp_$date.tar.gz /tmp &> /dev/null
11 rm -rf /tmp/dbback/db.txt
12 else
13 madir /tmp/dbback
14
15 echo "Date is : $date" > /tmp/dbback/db.txt
16 echo "Size is : $size" >> /tmp/dbback/db.txt
17 tar -zcf tmp_$date.tar.gz /tmp &> /dev/null
18 rm -rf /tmp/dbback/db.txt
19 fi
范例2 :判断apache是否启动
[root@mysql sh]# more if_test3.sh
#!/bin/bash
port=$(nmap -sT 192.168.160.10 | grep tcp | grep httpd | 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_acc.log
fi
多分支if
语句格式:
if [ 条件判断式1 ]
then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时,执行程序2
……省略更多条件
else
当所有条件都不成立时,最后执行此程序
fi
文件类型判断范例:
[root@mysql sh]# cat -n if_test4.sh
1 #!/bin/bash
2
3 read -p "Please input a filename :" file
4 #接收键盘的输入,并赋值给file
5
6 if [ -z "$file"]
7 #判断file是否为空
8 then
9 echo "Erro please input a filename"
10 exit 1
11 elif [ ! -e "$file" ]
12 #判断file的值是否存在
13 then
14 echo "Your put is not a file"
15 exit 2
16 elif [ -f "$file" ]
17 #判断file的值是否为普通文件
18 then
19 echo "file is a regulare file"
20 elif [ -d "$file" ]
21 #判断file是否为目录文件
22 then
23 echo "file is a directory"
24 else
25 echo "file is another file!"
26 fi
case
语句case语句只能匹配一种条件语句,if语句可以匹配多种条件语句。
格式:
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
范例:
[root@mysql sh]# cat -n /tmp/sh/case.sh
1 #!/bin/bash
2
3
4 read -p "Please choose yes/no " -t 30 cho
5 case $cho in
6 "yes")
7 echo "your choice is yes!"
8 ;;
9 "no")
10 echo "your choice is no!"
11 ;;
12 *)
13 echo "your choice is error!"
14 ;;
15 esac
语法1:
for 变量 in 值1 值2 值3……
do
程序
done
范例:
[root@mysql sh]# cat -n /tmp/sh/for2.sh
1 #!/bin/bash
2 #批量解压缩脚本
3
4 cd /lamp
5 ls *.tar.gz > ls.log
6 for i in $(cat ls.log)
7 do
8 tar -zxf $i &> /dev/null
9 done
10 rm -rf /lamp/ls.log
语法2:
for ((初始值;循环控制变量;变量变化))
do
程序
done
范例:
[root@mysql sh]# cat -n /tmp/sh/for3.sh
1 #!/bin/bash
2 #计算从1加到100
3
4 s=0
5 for ((i=1;i<=100;i=i+1))
6 do
7 s=$(( $s+$i ))
8 done
9 echo "The sum of 1+2+3+…… is: $s"
[root@mysql sh]# cat -n /tmp/sh/for4.sh
1 #!/bin/bash
2 #批量添加用户
3
4 read -p "Please input the username:" name
5
6 read -p "Please input the number of users:" num
7
8 read -p "Please input the password of users:" pass
9 if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ]
10 #判断三个输入是否都不为空
11 then
12 y=$(echo $num | sed 's/^[0-9]*$'//g)
13 #将以数字开头以任意字符结尾的num替换为空
14 if [ -z "$y" ]
15 then
16 for ((i=1;i<=num;i=i+1))
17 do
18 /usr/sbin/useradd $name$i &> /dev/null
19 echo $pass | usr/bin/passwd --stdin “$name$i” &>/dev/null
20 #stdin重定向输入,管道符接收前面指令结果作为后面指令的输入
21 done
22 fi
23 fi
while
循环与until
循环while 循环时不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样了。
语法:
while [ 条件判别式 ]
do
程序
done
范例:
[root@mysql sh]# cat -n /tmp/sh/while.sh
1 #!/bin/bash
2 #计算1到100的和
3
4 s=o
5 i=1
6 while [ $i -le 100 ]
7 do
8 s=$(( $s+$i ))
9 i=$(( $i+1 ))
10 done
11 echo "The sum is : $s"
until 循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
范例:
[root@mysql sh]# cat -n /tmp/sh/until.sh
1 #!/bin/bash
2
3 s=0
4 i=1
5 until [ $i -gt 100 ]
6 #循环直到变量i的值大于100
7 do
8 s=$(( $s+$i ))
9 i=$(( $i+1 ))
10 done
11 echo "The sum is :$s"