正则表达式和grep、vim、awk、sed等的关系:
- 正则表达式是一种方法,相当于一种工艺,grep等命令相当于是一个具体的加工机器,机器在加工产品的时候,采用这种方法。
命令是怎么执行的:
select工具
select是bash自带的字符菜单工具。
- 不需要echo命令就可以自动列出菜单
- 不需要read命令就可以读取变量的值
- 不需要赋值命令就可以自动赋值给变量
select基本语法:
PS3="select的提示符"
select variable in list
do
commands
done
例如:
#!/bin/bash
PS3="Please input the number:"
select number in "select A" "select B" "select C" "Exit"
do
case $number in
"select A")
echo "AAAAAAA"
;;
"select B")
echo "BBBBBBB"
;;
"select C")
echo "CCCCCCC"
;;
"Exit")
exit
;;
*)
echo -e"
"
echo "Sorry,haven't this item..."
esac
done
clear
执行结果:
通配符(globbing)
常用通配符:
- *: 匹配0个或者多个字符
- ? :匹配1个字符
- […] :匹配范围内任意1个字符 [az]、[a-z]、[a-z]
- [^…]: 匹配范围外任意1个字符,表示取反
- {} :组合匹配,touch a{1,3,5} touch b{1..10} touch {a,b,c}_{1,2,3}
例:
- [0-9] 代表数字
- [abcd123] 代表取中括号里的任意一个字符
- [a-Z] 代表大小写字母
- [0-Z] 代表0-9和所有的大小写字母
正则表达式里通配符和shell里面的通配符的区别:
- shell里面的通配符:用在bash里面
- 正则里面的通配符:用在真正的命令里面
grep命令详解
grep通用正则表达式分析程序(global research regular expression and printing):
其实,grep是一个过滤命令,根据特定的正则表达式来过滤文本里的内容。grep是根据某个模式进行匹配文件里的一行一行的数据去处理的,如果有匹配的行,就会将整行输出到屏幕上。
用途:使用正则表达式搜索文本,并把匹配的行打印出来
格式:grep [选项]… 模式 目标文件
- -v: 反转查找,输出与模式不相符的行 –》invert
- -An:同时显示符合条件行的下面n行 –》after-context
- -Bn:同时显示符合条件行的上面n行 –》before-context
- -Cn:同时显示符合条件行的上面n行和下面n行
- -E: 支持扩展正则表达式 –extended regular
- -o: 仅显示匹配的字符串 –》only-matching
- -f: 根据文件内容进行匹配
- -a:以文本文件方式搜索
- -c:计算找到的符合行的次数
- -i:忽略大小写 –》ignore-case
- -n:顺便输出行号 –》line-number
- -P “ ” –》得到Tab键 –》使用perl语言的正则语法,支持 表示tabl键,s表示空白
grep用的时候模式要用双引号”“引起来!!!
PS: 效率:grep>sed>awk
pattern模式:
- 模式其实就是一个公式,里面有字母+数字+特殊符号,组合成一个正则表达式,表达出某个含义。
(一行一行的处理–》文字流)
linux系统支持的三种形式的grep命令
Linux系统支持三种形式的grep命令,通常将这三种形式的grep命令称为grep命令族,这三种形式具体为:
- ①fgrep:不支持正则表达式,快速搜索简单模式,按照字符串的字面意思进行匹配,相当于grep -F
- ②grep:可以使用基本正则表达式搜索
- ③egrep:可以使用基本和扩展正则表达式搜索,相当于grep -E
PS:还有 ls /bin/*grep 也可。
正则表达式
一、正则表达式是一个指定文本模式的标准Unix 语法。
- 使用特殊元字符实现复杂的搜索问题。
- 元字符(meta characters)是用来阐释字符表达式意义的字符,简言之,元字符就是描述字符的字符,它用于对字符表达式的内容、转换及各种操作信息进行描述。
二、正则表达式是由一串字符和元字符构成的字符串,简称RE(Regular Expression)
- 基本正则表达式和Unix兼容
- 扩展正则表达式增加了一些新的元字符
三、正则表达式由下列元素构成 :
- 普通字符,a、b 、1、2
- 通配符,与文件名通配符不是一回事
- 修饰符:”*” ”?”等
- 锚点:以什么开头、以什么结尾
正则里的通配符:
- ①“.”:表示一定有一个任意字符
a…b 表示ab之间有三个字符
② 方括号表达式:一个文字字符域
- [abc] :a或者b或者c中的一个
- [^abc] :不是abc其中的一个
- [0-9]、[a-z]、[A-Z] : 数字、小写、大写
③域表达式和字符类
考虑到不同的编码方案推荐使用字符类方式(此类方法不常用,以被上面②方式代替!)- [:alnum:] -字母数字混排 等同于[0-Z]
- [:digit:] -数字 等同于[0-9]
- [:lower:] -小写字母 等同于[a-z]
- [:upper:] -大写字母 等同于[A-Z]
- [:space:] -空白字符,空格、TAB、换行符等
通用修饰符(理解为通配符即可):
- ?:表示0个或者1个前面的字符(0或1个)(扩展)
ab?c –》没有b或者只有一个b–》ac、abc - * :表示0个或者多个前面的字符(>=0个)
ab*c –》没有b或者多个b–》ac、abc、abbc、abbbc…… - +:表示1个或者多个前面的字符(>=1)
ab+c –》一个b或者多个b–》abc、abbc、abbc…… - {n}:表示n个前面的字符(前面的字符出现了n次)
ab{2}c–》b出现了两次-》abbc - {n,m}:表示n个到m个前面的字符
ab{2,4}c–》2个到4个b–》abbc、abbbc、abbbbc - .* –》点代表任意一个,*表示前面的0个或多个–》即所有字符 锚点搜索
- ^:表示以什么开头行
- $:表示以什么结尾的行。bash$–》以bash结尾的行
- <:表示词首部 或者
wubing :以wubing开头 - >:表示词尾部 或者
wubing:以wubing结尾 - < abc >:表示abc这个单词 等价于 abc。
<wubing> 表示wubing这个单词
PS: grep在界定单词的时候,默认使用的分隔符是空白
扩展正则表达式
egrep、awk和Perl等Linux工具还支持正则表达式扩展出来的一些元字符,这些元字符如下表所示:
- ?:匹配0个或1个在其之前的那个普通字符
- +:匹配1个或多个在其之前的那个普通字符
- ( ):表示一个字符集合
- | :表示’或’,匹配一组可选的字符
正则表达式分组
- ①“?”、”*”、”+”默认只能修饰前面一个字符
- ② 利用圆括号( )可以实现多个字符分组
f(oo)*: 因为oo括起来了,所以把oo看成”一个字符”,即f、foo、foooo …… - ③在圆括号中利用”|”实现或者的功能
echo foooeee | egrep –color “(oo|ee){2}”
echo foooeee | egrep –color “(oo|ee){1}”
转义元字符
egrep ‘cat.' /etc/aa
egrep ‘cat.' /etc/aa
正则表达式与通配符匹配的区别
- 正则表达式只在少数搜索和替换文本命令中使用
- 文件名匹配在bash中匹配文件名
- 都使用”*”、”?”但意义不一样
- 正则表达式元字符要放在引号内,避免bash Shell解释
PS:tab键怎么grep匹配出来:
①egrep “s”–》s表示空白(空格、tab、换行符)
②egrep “[[:space:]]” –》查找空白(空格、tab、换行符)
③grep -P “ “ –》得到Tab键 –》使用perl语言的正则语法,支持 表示tabl键,s表示空白
IP的正则
写ip地址正则时的方法:需要按个位(1位)、十位(2位)、百位(3位)
显示文件中的所有A类地址:(1-126)
"([1-9]|[1-9][0-9]|1[01][0-9]|12[0-6])(.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ){3}"
- 先写的个位,再十位。百位先写的100-119,再120-126;
- 0-255,先0-9,再10-99,100-199,200-249,最后250-255
显示文件中的所有B类地址:(128-191)
"(12[89]|1[3-8][0-9]|19[01])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]) ){3}"
显示文件中的所有C类地址:(192-223)
"(19[2-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]) ) {3}"
匹配email地址:
egrep "[0-Z._]+@[0-Z]+.[a-Z]+"
匹配HTTP URL:
egrep "^http://([0-Z]+.){2}[a-Z]{2,3}"
egrep --color "http://(.*..*){2}" --》网址至少有两个点!(适用所有网址)
shell中的特殊字符
- :冒号
- 内置的空命令,返回值为0–》while :
- ;分号
- 连续运行命令
- | 管道
- 前面命令的标准输出作为后面命令的标准输入
- 正则中表示或者
- &
- 将命令放到后台执行
- 表示标准输出和标准错误输出
- &&
- 前面命令执行成功才执行后面的命令
- ||
- 前面命令执行不成功才执行后面的命令
- # 井号
- 表示注释
- ? 问号
- 通配符中表示任意1个字符
- 正则表达式中表示0个或者1个前面的字符
- *星号
- 通配符中表示0个到多个任意字符
- 正则表达式中表示0个或者多个前面的字符
- 算术运算中的乘法
- !惊叹号
- 将命令或者条件表达式的返回值取反
- 执行历史命令
- vi或者ftp中执行外部shell命令
- 间接应用变量 –》${!b}
- $ 美元符号
- 取变量的值
- 正则表达式表示行尾
- 反斜杠
- 单字符转义
- > 大于号
- 输出重定向
- 条件测试中的大于号
- < 小于号
- 输入重定向
- 条件测试中的小于号
- = 等号
- 变量赋值
- 条件测试中的等号
- +加号
- 算术运算中的加号
- 正则表达式中1个或多个前面的字符
- >>
- 输出重定向追加
- <<
- here document
- -减号
- 算术运算中的减号
- 命令的选项
- 上一次工作目录
- 通配符和正则表达式中表示范围[a-z]
- tar -cvf - /home | tar -xvf - 表示输出流或输入流
- ’ 单引号
- 解决变量赋值空格的问题
- 阻止shell替换
- “” 双引号
- 解决变量赋值空格的问题
- 阻止shell部分字符替换,对$、!等无效
- ` 反引号$()
- 命令行替换
- % 百分号
- 算术运算中的模运算
- vi中替换操作中表示所有行
- () 单圆括号
- 子shell中执行命令,会继承父shell的变量
- 括起数组元素
- (()) 双圆括号
- 算术运算
- 整数比较测试
- [] 单方括号
- 通配符和正则中表示匹配括号中的任意一个字符
- 条件测试表达式
- 数组中下标括号
- [[]] 双方括号
- 字符串比较测试 –》不能比较小数!比较小数要用bc计算机–》echo “4.5>5.5”|bc ,返回值为0,假的
- . 句点号
- 正则中表示任意1个字符
- 当前shell执行脚本命令
- 表示当前目录
- {} 大括
- 通配符扩展 abc{1,2,3}
- 正则表达式中表示范围
- 匿名函数{cmd1;cmd2;cmd3} &> /dev/null
- 括起变量名${abc}a
- / 正斜杠
- 算术运算中的除法
- 根目录或路径分割符
- ^ 乘方符
- 在[^abc]通配符中表示取反
- 在正则表达式中表示以什么开头
grep命令练习:
1.进入/lianxi目录,复制/etc/passwd到当前目录下,然后对passswd进行操作
2.查找出当前passwd文件中以ftp开头或者mail开头的行,在屏幕输出
3.查找出当前passwd文件中首行不是以r、m、f开头的行,在屏幕输出
4.查找出当前passwd文件中以bash结尾的行
5.查找出/etc/login.defs文件中的有效行(不显示空行和注释行)
6.查找出/var/log/messages文档中有16个字母的单词
7.查找/etc/passwd文件里用户名包含liu同时使用bash的用户
8.查找/etc/ssh/sshd_config文件里的有效行
9.查找/etc/ssh/sshd_config文件里的包含连续2个数字的行
10.查找出包含特殊字符的行
11.查找出不包含数字的行
12.查找出/var/log/messages里的ip地址出来
13.写一个正则来表示出下面的网址,例如:
http://www.baidu.com
http://www.sina.com
http://www.163.com
http://www.12306.cn
http://www.qillu.edu
14.写一个表示邮箱的正则,例如:
feng@qq.com
1234feng@163.com
meng.xianhui@yahoo.cn
liudenghua@sina.com
10001@qq.com
123_ui@12306.com
qilu@qilu.edu
15.C类ip地址的正则表达式
section1:范围在192-223之间
section2和section3和section4范围:0-255之间
例如:193.168.23.1
答案:
1)cp /etc/passwd .
2)cat passwd|grep "^ftp|^mail"
3)cat passwd|grep -v "^r|^m|^f"
4)cat passwd|grep "bash$"
5)cat /etc/login.defs|egrep -v "^$|^#"
6)cat /var/log/messages|egrep "<[0-Z]{16}>"
7)
法1: cat /etc/passwd|egrep "^[0-Z]*liu[0-Z]*" | egrep "bash"
法2: cat /etc/passwd|egrep "^.*liu.*:x:"|egrep "bash"
法3: cat /etc/passwd|egrep "^[0-Z_]*liu.*bash$"
8)cat /etc/ssh/sshd_config|egrep -v "^$|^#"
9)cat /etc/ssh/sshd_config|egrep "[0-9]{2}" --》连续两个数字
10)cat /etc/ssh/sshd_config|egrep "[^0-Z]" --》包含特殊字符(^在[]里面,表示取反)
11)cat /etc/passwd|grep -v ".*[0-9].*"
12)cat /var/log/messages | egrep "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ){3}"
13)egrep --color "http://(.*..*){2}" --》网址至少有两个点!(适用所有网址)
14)egrep "[0-Z._]{1,16}+@[0-Z]+.[a-Z]+" --》邮箱的正则(用户名最大16位)
15)"(19[2-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]) ) {3}" --》C类IP地址
PS:连续匹配和单独的字符混合使用
cat m_phone.txt|egrep -v "^[0-Z .]*$"
练习1:
监控/var/log/secure文件,统计出ssh错误连接本机次数超过十次的ip地址,拒绝这个ip地址再ssh连接过来(将这个ip地址写入到/etc/hosts.deny黑名单,/etc/hosts.allow是白名单)
分析:
#cat secure|egrep "Faild passwd"|egrep -o "172(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}" --》-o 只显示截出来的IP
上面的命令接 | sort | uniq -c | sort -nr –》uniq -c统计重复次数
得到 :
然后用while read aa bb,然后,echo “sshd:$bb” >>/etc/hosts.deny
答案:
#!/bin/bash
while true
do
cat secure|egrep "Failed passwd"|egrep -o "192(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"|sort|uniq -c|sort -nr >secure.txt
deny=$(cat /etc/hosts.deny|egrep "^sshd:192(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"|awk -F: '{print $2}')
echo $deny >deny_ip.txt
cat secure.txt|while read times IP
do
if (( $times>=2 ))
then
if ! grep $IP deny_ip.txt &>/dev/null
then
echo "sshd:$IP" >>/etc/hosts.deny&&echo "$IP has been written to /etc/hosts.deny"
fi
fi
done
sleep 1
done
练习2:编写判断IP地址是否合法的脚本
①提醒用户输入ip地址
②要求判断文件中的ip地址是否是合法的ipv4地址
③不合法的ip地址给与提醒
④输出用户输入的ip地址
分析:首先有三个点,其次,第一部分为1-223,其他为0-255即可。
答案:
cat /lianxi/iphefa.sh
#!/bin/bash
while :
do
clear
read -p "Please input the IP:" addr
echo "$addr" >iphefa.txt
if ( (cat "iphefa.txt"|egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$")&>/dev/null )
then
echo "The IP that you input is :$addr"
break
else
echo "Please input the right IP!!"
read -p "Please input anykey to continue......"
fi
done
练习3:
编写脚本实现显示当前主机eth接口的有效IP和有效网关,要求显示结果如下图所示(多使用正则表达式,少用cut和tr)
分析:route -n–》看网关,ifconfig–》看ip,
答案:
cat /lianxi/eth01.sh
#!/bin/bash
ifconfig|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"|head -n +2|tr -s " " ":"|cut -d":" -f4,6,8|tr -s ":" " " >eth01.txt
n=0
for i in $(<eth01.txt)
do
((n++))
if (( n==1 ))
then
(echo $i|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"&>/dev/null)&&echo "eth0:$i"||echo "no IP"
elif (( n==4 ))
then
(echo $i|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"&>/dev/null)&&echo "eth1:$i"||echo "no IP"
fi
done
route -n|tail -n 1 >GATEWAY.txt
cat GATEWAY.txt|while read a IP c d e f g ETH
do
if ( echo $IP|egrep "([1-9]|[1-9][0-9]|1[0-9][0-9]|2[01][0-9]|22[0-3])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}"&>/dev/null )
then
echo "gateway: $IP ($ETH)"
else
echo "gateway: NULL"
fi
done