正则,grep命令详解


正则表达式和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
原文地址:https://www.cnblogs.com/lpeng94/p/12546496.html