目录
1 基础正则表达式
1.1 正则表达式与通配符
1.2 基础正则表达式
1.3 正则表达式练习
2 字符截取命令
2.1 cut字段提取命令
2.1.1 cut命令的局限
2.2 printf命令
2.2.1 print和printf命令
2.3 awk命令
2.3.1 BEGIN
2.3.2 END
2.3.3 FS内置变量
2.3.4 关系运算符
2.4 sed命令
3 字符处理命令
3.1 排序命令sort
3.2 统计命令wc
4 条件判断
4.1 判断文件类型
4.2 判断文件权限
4.3 比较文件
4.4 比较整数
4.5 判断字符串
4.6 多重条件判断
5 流程控制
5.1 if语句
5.1.1 单分支if条件语句
5.1.2 双分支if条件语句
5.1.3 多分支if条件语句
5.2 case语句
5.3 for循环
5.3.1 语法一
5.3.2 语法二
5.4 while循环与until循环
5.4.1 while循环
5.4.2 until循环
6 函数
1 基础正则表达式
1.1 正则表达式与通配符
1.2 基础正则表达式
1.3 正则表达式练习
练习准备:创建一个名为“test_rule.txt”的文件,内容如下:
Mr. Li Ming said:
he was the honcst man in LampBrother.
123despise him.
But since Mr. shen Chao came,
he never saaaid those words.
5555nice!
because, actuaaaally,
Mr. Shen Chao is the most honest man!
Later,Mr. Li ming soid his hot body.
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 "s[ao]id" test_rule.txt? ??# 匹配s和i字母中,要不是a、要不是o
grep "[0-9]" test_rule.txt? ??# 匹配任意一个数字
grep "^[a-z]" test_rule.txt? ??# 匹配用小写字母开头的行
grep "^[a-z]" test_rule.txt? ??# 匹配不用小写字母开头的行
grep "^[a-zA-Z]" test_rule.txt? ??# 匹配不用字母开头的行 “\” 转义符
grep "\.$" test_rule.txt? ??# 匹配使用“.”结尾的行
grep "a\{3\}" test_rule.txt? ??# 匹配a字母连续出现三次的字符串
grep "[0-9]\{3\}" test_rule.txt? ??# 匹配包含连续的三个数字的字符串
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 字符截取命令
2.1 cut字段提取命令
命令格式:cut [选项] 文件名
选项:
- -f 列号: 提取第几列
- -d 分隔符: 按照指定分隔符分割列(默认以“\t”为分隔符)
练习文件:创建一个名为“student.txt”的文件,内容如下
ID Name gender Mark
1 Liming M 86
2 Sc M 90
3 Gao M 83
cut -f 2 student.txt? ? #?提取第二列
cut -f 2,3 student.txt? ??# 提取第二第三列
cut -d ":" -f 1,3 /etc/passwd? ??# 以“:”为分隔符提取第一第三列
2.1.1 cut命令的局限
df -h | cut -d " " -f 5? ? # 提取“已用%”列数据
注意:有多个空格时提取会出问题
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键
练习1:
printf %s 1 2 3 4 5 6
printf %s %s %s 1 2 3 4 5 6
printf '%s %s %s' 1 2 3 4 5 6
printf '%s %s %s\n' 1 2 3 4 5 6
小贴士:三个看成一个整体所以123是一个整体,456是另一个。所以在3后面换行
练习2:创建一个名为“student.txt”的文件,内容如下
ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66
printf '%s' $(cat student.txt)? ? # 不调整输出格式
printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $(cat student.txt)? ??# 调整格式输出
2.2.1 print和printf命令
在awk命令的输出中支持print和printf命令
2.3 awk命令
命令格式:awk ‘条件1{动作1} 条件2{动作2}…’ 文件名
条件(Pattern):
- 一般使用关系表达式作为条件
- x > 10 判断变量 x是否大于10
- x>=10 大于等于
- x<=10 小于等于
动作(Action):
- awk '{printf $2 "\t" $6 "\n"}' student.txt? ? # 格式化输出第2、6列内容
- df -h | grep /dev/sda2 | awk '{printf $5 "\n"}' | cut -d "%" -f 1? ? # 获取根目录的内存占用率
2.3.1 BEGIN
说明:在命令开始前执行
- awk 'BEGIN{printf "This is a transcript \n" } {printf $2 "\t" $6 "\n"}' student.txt? ? # 在标准化输出前输出“This is a transcript \n”
2.3.2 END
说明:在命令执行结束后执行
- awk 'END{printf "The End \n" } {printf $2 "\t" $6 "\n"}' student.txt? ? # 在标准化输出结束后输出“The End \n”
2.3.3 FS内置变量
说明:指定分隔符
- cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'
小贴士:如果不在{FS=":"} 前边加“BEGIN”,第一行会有问题
2.3.4 关系运算符
- cat student.txt | grep -v Name | awk '$6 >= 87 {printf $2 "\n" }'
2.4 sed命令
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
命令格式:sed [选项] ‘[动作]’ 文件名
选项:
- -n: 一般sed命令会把所有数据都输出到屏幕 , 如果加入此选择,则只会把经过 sed命令处 理的行输出到屏幕。
- -e: 允许对输入数据应用多条sed命令编辑
- -i: 用sed的修改结果直接修改读取数据的文件, 而不是由屏幕输出
动作:
- a \: 追加,在当前行后添加一行或多行。添加多行时,除最后 一行 外,每行末尾需要用“\”代 表数据未完结。
- c \: 行替换,用c后面的字符串替换原数据行,替换多行时,除最 后一行外,每行末尾需“\”代 表数据未完结。
- i \: 插入,在当期行前插入一行或多行。插入多行时,除最后 一行 外,每行末尾需要“\”代
- 表数据未完结。
- d: 删除,删除指定的行。
- p: 打印,输出指定的行。
- s: 字串替换,用一个字符串替换另外一个字符串。格式为“行范 围s/旧字串/新字串/g”(和vim中的替换格式类似)。
常用命令
行数据操作
- sed '2p' student.txt? ??# 查看文件的第二行
- sed -n '2p' student.txt? ??# 只查看文件的第二行
- sed '2,3d' student.txt? ? # 删除第二行到第三行的数据,但不修改文件本身
- sed '2a hello' student.txt? ? # 在第二行后追加hello
- sed '2i hello world' student.txt? ??# 在第二行前插入两行数据
- sed '2c No such person' student.txt? ??# 将第2行数据进行替换
字符串替换:sed ‘s/旧字串/新字串/g’ 文件名
- sed '3s/74/99/g' student.txt? ? # 在第三行中,把74换成99
- sed -i '3s/74/99/g' student.txt? ? # sed操作的数据直接写入文件(不建议)
- sed -e 's/Liming//g ; s/Gao//g' student.txt? ? # 同时把“Liming”和“Gao”替换为空
3 字符处理命令
3.1 排序命令sort
命令格式:sort [选项] 文件名
选项:
- -f: 忽略大小写
- -n: 以数值型进行排序,默认使用字符串型排序
- -r: 反向排序
- -t: 指定分隔符,默认是分隔符是制表符
- -k n[,m]: 按照指定的字段范围排序。从第n字段开始, m字段结束(默认到行尾)
常用命令
sort /etc/passwd? ??# 排序用户信息文件
sort -r /etc/passwd? ?# 反向排序
sort -t ":" -k 3,3 /etc/passwd? ? # 指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序
sort -n -t ":" -k 3,3 /etc/passwd? ? #?以数值型进行排序
3.2 统计命令wc
命令格式:wc [选项] 文件名
选项:
- -l: 只统计行数
- -w: 只统计单词数
- -m: 只统计字符数
常用命令
wc -l /etc/passwd? ??#?统计文件行数
wc -w?/etc/passwd? ?# 统计文件单词数
df -h | wc? ? # 统计命令结果行数
4 条件判断
两种判断格式
- test -e /root/install.log
- [ -e /root/install.log ]
小贴士:
????????一般用第二种格式,且需要注意中括号[]与命令之间一定要有空格,否则会报错。
? ? ? ? echo $?? ? # 查看上一条命令结果:0为执行正确;非0为执行错误
4.1 判断文件类型
- [ -d /root ] && echo "yes" || echo "no"? ? # 第一个判断命令如果正确执行,则打印“yes”,否则打印“no”
4.2 判断文件权限
- [ -w student.txt ] && echo "yes" || echo "no"? ??# 判断文件是拥有写权限的
小贴士:只有该文件拥有写权限就返回真,无法判断具体用户是否拥有写权限
4.3 比较文件
- ln /root/student.txt /tmp/stu.txt? ? #?创建个硬链接
- [ /root/student.txt -ef /tmp/stu.txt ] && echo "yes" || echo "no" yes? ? # 用test进行测试
4.4 比较整数
- [ 23 -ge 22 ] && echo "yes" || echo "no"? ? # 判断23是否大于等于22,当然是了
- [ 23 -le 22 ] && echo "yes" || echo "no"? ? # 判断23是否小于等于22,当然不是了
4.5 判断字符串
常用命令
name=sc? ??# 给name变量赋值
[ -z "$name" ] && echo "yes" || echo "no"? ??#判断name变量是否为空,因为不为空,所以返回no
aa=11
bb=22? ? # 给变量aa和变量bb赋值
[ "$aa" == "$bb" ] && echo "yes" || echo "no"? ??#判断两个变量的值是否相等,明显不相等,所以返回no
4.6 多重条件判断
常用命令
aa=11
[ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no"? ??#判断变量aa是否有值,同时判断变量aa的是否大于23
[ -n "$aa" -a "$aa" -lt 23?] && echo "yes" || echo "no"
5 流程控制
5.1 if语句
5.1.1 单分支if条件语句
if [ 条件判断式 ] ; then
程序
fi
#或者
if [ 条件判断式 ]
then
程序
fi
单分支条件语句需要注意几个点
-
if语句使用fi结尾,和一般语言使用大括号结尾不同 -
[ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格 -
then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了
案例:判断分区使用率
#!/bin/bash
# 统计根分区使用率
# Author: Apollo
rate=$(df -h | grep "/dev/sda2" | awk '{print $5}' | cut -d "%" -f 1)
# 把根分区使用率作为变量值赋予变量rate
if [ $rate -ge 10 ]
then
echo "Warning! /dev/sda3 is full!"
fi
5.1.2 双分支if条件语句
if [ 条件判断式 ]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
案例1:备份配置目录/etc
#!/bin/bash
#备份配置目录/etc。
# Author:Apollo
ntpdate asia.pool.ntp.org &> /dev/null
#同步系统时间
date=$(date +%Y%m%d)
#把当前系统时间按照“年月日”格式赋予变量
datesize=$(du -sh /etc)
#统计配置目录/etc的大小,并把大小赋予size变量
if [ -d /tmp/etc_bak ]
then
echo "Date:$date!" > /tmp/etc_bak/etc_info.txt
echo "Datasize:$size" >> /tmp/etc_bak/etc_info.txt
cd /tmp/etc_bak
tar -zcf etc-$date.tar.gz /etc etc_info.txt &> /dev/null
rm -rf /tmp/etc_bak/etc_info.txt
else
mkdir /tmp/etc_bak
echo "Date:$date!" > /tmp/etc_bak/etc_info.txt
echo "Datasize:$size" >> /tmp/etc_bak/etc_info.txt
cd /tmp/etc_bak
tar -zcf etc-$date.tar.gz /etc etc_info.txt &> /dev/null
rm -rf /tmp/etc_bak/etc_info.txt
fi
案例2:判断apache是否启动
#!/bin/bash
#Author:Apollo
port=$(nmap -sT 192.168.31.222 | grep 80/tcp | grep http | awk '{print $2}')
#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量port
echo ${port}
if [ "$port" == "open" ]
then
echo "$(date) httpd is ok!" >> /tmp/autostart-acc.log
else
/usr/sbin/httpd -k start &> /dev/null
echo "$(date) restart httpd!!" >> /tmp/autostart-err.log
fi
5.1.3 多分支if条件语句
if [ 条件判断式1 ]
then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时,执行程序2
...省略更多条件...
else
当所有条件都不成立时,最后执行此程序
fi
案例:
#!/bin/bash
#判断用户输入的是什么文件
#Author:Apollo
read -p "Please input a file name: " file
#接收键盘的输入,并赋予变量file
if [ -z "$file" ]
#判断file变量是否为空
then
echo "Error, please input a file name"
exit 1
elif [ ! -e "$file" ]
#判断file的值是否存在
then
echo "You input is not a file!"
exit 2
elif [ -f "$file" ]
#判断file的值是否为普通文件
then
echo "$file is a regulare file!"
elif [ -d "$file" ]
#判断file的值是否为目录文件
then
echo "$file is a directory!"
else
echo"$file is another file!"
fi
5.2 case语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
多分支case条件语句
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
* )
如果变量的值都不是以上的值,则执行此程序
;;
esac
案例:
#!/bin/bash
#判断用户输入
#Author:Apollo
read -p 'Please chose "yes"/"no":' -t 30 cho
case $cho in
"yes")
echo "Your choice is yes!"
;;
"no")
echo "Your choice is no!"
;;
*)
echo "Your choice is error!"
;;
esac
5.3 for循环
5.3.1 语法一
这种情况适用于不知道循环次数
for 变量 in 值1 值2 值3
do
程序
done
案例1:
#!/bin/bash
#for循环输出
#Author:Apollo
for city in beijing nanjing shanghai
do
echo "this city is $city "
done
案例2:
#!/bin/bash
#批量打包脚本
#Author:Apollo
cd /root/sh
ls *.sh > ls.log
for i in $(cat ls.log)
do
tar -zcf $i.tar.gz $i &> /dev/null
done
rm -rf ls.log
5.3.2 语法二
这种情况适用于知道循环次数
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
案例1:
#!/bin/bash
#从1加到100
#Author:Apollo
num=0
for(( i=1;i<=100;i++ ))
do
num=$(( $num+$i ))
done
echo "this sum of 1+2+...+100 is: $num"
案例2:
#!/bin/bash
#Author:Apollo
#批量添加新用户
read -p "Please input user name: " -t 30 name # 输入用户名,等待时间30s
read -p "Please input the number of users: " -t 30 num # 输入创建用户个数,等待时间30s
read -p "Please input the password of users: " -t 30 pass # 输入用户密码,等待时间30s
if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ] # 判断输入信息是否为空
then
y=$(echo $num | sed s/[0-9]//g) # 这里是判断输入的用户个数是否为数字,sed后也可以把s/[0-9]//g换为^[0-9]*$
if [ -z "$y" ] # 如果上一条语句输出不为空,就是输入的用户个数为数字,继续执行
then
for ((i=1;i<=$num;i++)) # 开始循环
do
/usr/sbin/useradd "$name$i" &>/dev/null # 建立用户
echo $pass | /usr/bin/passwd --stdin "$name$i" &>/dev/null #设置用户密码,与用户名相同
done
echo "Build seccees!"
fi
fi
5.4 while循环与until循环
5.4.1 while循环
while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样了。
while [ 条件判断式 ]
do
程序
done
案例:从1加到100
#!/bin/bash
#从1加到100
#Author:shenchao(E-mail:shenchao@lampbrother.net)
i=1
s=0
while [ $i -le 100 ]
#如果变量i的值小于等于100,则执行循环
do
s=$(($s+$i))
i=$(($i+1))
done
echo"Thesumis:$s"
5.4.2 until循环
until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
until [ 条件判断式 ]
do
程序
done
案例:从1加到100
#!/bin/bash
#从1加到100
#Author:Apollo
i=1
s=0
until [ $i -gt 100 ]
#循环直到变量i的值大于100,就停止循环
do
s=$(( $s+$i ))
i=$(( $i+1 ))
done
echo"The sum is: $s"
6 函数
[ function ] funname [()]{
action;
[return int;]
}
小贴士:
- [] -> 表示可以省略
- 在以上的函数语法中,前面的funcation 表示声明一个函数!!! 可以不写
- return -n 是指退出函数
案例:
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read a
echo "输入第二个数字: "
read b
echo "两个数字分别为 $a 和 $b !"
return $(( $a+$b ))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
|