Day17-正则表达式
作者:mmseoamin日期:2024-04-27

Day17-正则表达式

  • 1. 正则表达式介绍
    • 1.1 什么是正则表达式?
    • 1.2 Linux三剑客的正则表达式有如下特点:
    • 1.3 基础正则表达式字符说明及实践:
    • 1.4 测试题:
    • 1.5 扩展正则:
    • 1.6 扩展正则测试题:
    • 1.7 【元字符】
    • 1.8 特殊预定义表达式
    • 2. Sed命令语法及参数说明

      双引号使用:

      grep oldboy /etc/passwd

      grep “oldboy” /etc/passwd

      echo oldgirl

      echo “oldgirl”

      find /etc/ -name “*.conf”

      1. 正则表达式介绍

      1.1 什么是正则表达式?

      简单地说,正则表达式就是为处理大量的字符串及文本定义的一套规则和方法。假设”@“代表“I am”,“!”代表“oldboy”,则执行echo “@!”的结果就是输出“I am oldboy”。通过这些特殊符号的辅助,管理员就可以快速过滤、替换或输出需要的字符串,让Linux运维更高效。

      1.2 Linux三剑客的正则表达式有如下特点:

      • 为处理大量文本及字符串而定义的一套规则和方法
      • 其工作时以行为单位进行,即一次处理一行
      • 通过正则表达式可以将复杂的处理任务化繁为简,提高操作Linux的效率
      • 仅被三剑客(grep/egrep、sed、awk)命令支持,其他命令无法使用

        做 写 想 【讲】

        alias net='cat /etc/sysconfig/network-scripts/ifcfg-eth0'
        

        测试准备:

        cat >>/etc/profile<~/test/oldboy.txt< 
        

        1.3 基础正则表达式字符说明及实践:

        给要过滤的内容添加标识,然后把符合标识的内容过滤。

        字符作用
        ^尖角号,用法为^oldboy,表示匹配以oldboy单词开头的行
        $美元符,用法为oldboy$,表示匹配以oldboy单词结尾的行
        ^$组合符,表示空行,逻辑解释就是以^结尾的行,或者以$开头的行
        .点号,表示匹配任意一个且只有一个字符(但是不能匹配空行)
        \转义字符,让有特殊含义的字符脱掉马甲,现出原形,如\.只表示小数点
        *匹配前一个字符(连续出现)0次或1次以上 注意,当重复0次的时候,表示啥也没有(空),即匹配所有内容
        .*组合符,匹配所有内容
        ^.*组合符,匹配以任意多个字符开头的内容
        .*$组合符,以任意多个字符结尾的内容
        [abc]匹配[]集合内的任意一个字符a或b或c;[abc]也可写成[a-c]
        [^abc]匹配不包含后的任意字符a或b或c,这里的表示对[abc]的取反,^不能用!替代

        ^ 尖角号,用法为^oldboy,表示匹配以oldboy单词开头的行

        [root@oldboy test]# grep ^I oldboy.txt #输出以I开头的行
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        [root@oldboy test]# ls -l ~|grep ^d #输出以d开头的行
        drwxr-xr-x. 2 1000 root       33 Jul  1  2030 abc
        drwxr-xr-x. 2 root root       45 Jun  6  2019 girlLove
        drwxr-xr-x. 3 root root       17 May  8  2021 oldboy_dir
        drwxr-xr-x. 2 root root       24 May 25 11:24 test
        

        $ 美元符,用法为oldboy$,表示匹配以oldboy单词结尾的行

        [root@oldboy test]# grep m$ oldboy.txt #输出以m结尾的行
        our site is http://www.oldboyedu.com
        [root@oldboy test]# ls -lF ~|grep /$
        drwxr-xr-x. 2 1000 root       33 Jul  1  2030 abc/
        drwxr-xr-x. 2 root root       45 Jun  6  2019 girlLove/
        drwxr-xr-x. 3 root root       17 May  8  2021 oldboy_dir/
        drwxr-xr-x. 2 root root       24 May 25 11:24 test/
        

        ^$ 组合符,表示空行,逻辑解释就是以^结尾的行,或者以$开头的行

        [root@oldboy test]# cat oldboy.txt -n
             1	I am oldboy teacher!
             2	I teach linux.
             3	
             4	I like badminton ball ,billiard ball and chinese chess!
             5	our site is http://www.oldboyedu.com
             6	my qq num is 49000448.
             7	
             8	not 4900000448.
             9	my god ,i am not oldbey,but OLDBOY!
        [root@oldboy test]# grep ^$ oldboy.txt 
        [root@oldboy test]# grep -n ^$ oldboy.txt  #输出空行并打印行号
        3:
        7:
        

        . 点号,表示匹配任意一个且只有一个字符(但是不能匹配空行)

        [root@oldboy test]# grep . oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        [root@oldboy test]# grep -n . oldboy.txt 
        1:I am oldboy teacher!
        2:I teach linux.
        4:I like badminton ball ,billiard ball and chinese chess!
        5:our site is http://www.oldboyedu.com
        6:my qq num is 49000448.
        8:not 4900000448.
        9:my god ,i am not oldbey,but OLDBOY!
        

        \ 转义字符,让有特殊含义的字符脱掉马甲,现出原形,如\.只表示小数点

        [root@oldboy test]# grep "\." oldboy.txt #匹配带点的行
        I teach linux.
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        [root@oldboy test]# grep "\.$" oldboy.txt #匹配以点结尾的行
        I teach linux.
        my qq num is 49000448.
        not 4900000448.
        [root@oldboy test]# grep ".$" oldboy.txt  #匹配以任意一个字符结尾的行
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        

        * 重复前一个字符(连续出现)0次或N次

        0*

        0

        00

        00000

        [root@oldboy test]# grep "0*" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        [root@oldboy test]# grep "00*" oldboy.txt 
        my qq num is 49000448.
        not 4900000448.
        

        注意,当重复0次的时候,表示啥也没有(空),即匹配所有内容

        .* 组合符,匹配所有内容

        [root@oldboy test]# grep ".*" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        

        ^.* 组合符,匹配以任意多个字符开头的内容

        [root@oldboy test]# grep "^.*" oldboy.txt
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        

        .*$ 组合符,以任意多个字符结尾的内容

        [root@oldboy test]# grep ".*$" oldboy.txt
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        

        1.4 测试题:

        1.过滤/etc/passwd中以nologin结尾的行。

        grep "nologin$" /etc/passwd
        

        2.过滤/etc/passwd中以o开头的行。

        grep "^o" /etc/passwd
        

        3.过滤/etc/passwd中至少含有1个0字符串的行。

        grep "00*" /etc/passwd
        

        4.过滤/etc/passwd中的空行。

        grep "^$" /etc/passwd
        

        5.过滤/etc/目录中(不含子目录)下的所有文件。

        ls -l /etc|grep "^-"
        

        6.过滤/etc/services中含有点号的行。

        grep "\." /etc/services
        

        [abc] 匹配[]集合内的任意一个字符a或b或c;[abc]也可写成[a-c]

        [root@oldboy test]# grep "[a-z0-9A-Z\.\!:,/]" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        [root@oldboy test]# grep "." oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        

        [^abc] 匹配不包含后的任意字符a或b或c,这里的表示对[abc]的取反,^不能用!替代

        [root@oldboy test]# grep "[a-z0-9A-Z]" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        [root@oldboy test]# 
        [root@oldboy test]# 
        [root@oldboy test]# 
        [root@oldboy test]# 
        [root@oldboy test]# grep "[^a-z0-9A-Z]" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        

        1.5 扩展正则:

        字符作用
        +匹配前一个字符1次或多次
        [😕]+匹配括号内的:或/字符1次或多次
        匹配前一个字符0次或1次
        |表示或者,即同时过滤多个字符串
        ()分组过滤被括起来的东西表示一个整体,另外()的内容可以被后面的\n引用,n为数字,表示引用第几个括号的内容
        \n引用前面()小括号里的内容,例如:(aa),匹配aaaa
        a{n,m}匹配前一个字符最少n次,最多m次
        a{n,}匹配前一个字符最少n次
        a{n}匹配前一个字符正好n次
        a{,m}匹配前一个字符最多m次

        grep -E ====egrep

        + 匹配前一个字符1次或多次

        和*区别,*可以匹配0次。

        grep “0*” oldboy.txt #匹配0个0,或1个0或多个0

        egrep “0+” oldboy.txt #1个0或多个0

        [root@oldboy test]# grep "0*" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        [root@oldboy test]# egrep "0+" oldboy.txt
        my qq num is 49000448.
        not 4900000448.
        

        [😕]+ 匹配括号内的:或/字符1次或多次

        [root@oldboy test]# cat a.txt 
        oldboy
        [root@oldboy test]# egrep -o "." a.txt 
        o
        l
        d
        b
        o
        y
        [root@oldboy test]# egrep "[:/]+" oldboy.txt 
        our site is http://www.oldboyedu.com
        :::
        ///
        :d::f
        /etc/oldboy//
        [root@oldboy test]# egrep "[:/]" oldboy.txt 
        our site is http://www.oldboyedu.com
        :::
        ///
        :d::f
        /etc/oldboy//
        

        ? 匹配前一个字符0次或1次

        [root@oldboy test]# egrep "0?" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        :::
        ///
        :d::f
        /etc/oldboy//
        

        | 表示或者,即同时过滤多个字符串

        [root@oldboy test]# egrep "000|oldboy" oldboy.txt 
        I am oldboy teacher!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        /etc/oldboy//
        

        ()分组过滤被括起来的东西表示一个整体

        另外()的内容可以被后面的\n引用,n为数字,表示引用第几个括号的内容

        \n 引用前面()小括号里的内容,例如:(aa)\1,匹配aaaa

        [root@oldboy test]# egrep "(0)(0)" oldboy.txt 
        not 4900000448.
        

        \1可以取出第1个括号的内容

        \2可以取出第2个括号的内容。

        sed命令

        (下面几个没啥用)

        a*

        a+

        a{n,m} 匹配前一个字符最少n次,最多m次

        a{n,} 匹配前一个字符最少n次

        a{n} 匹配前一个字符正好n次

        a{,m} 匹配前一个字符最多m次

        实践:

        [root@oldboy test]# egrep "0{3,4}" oldboy.txt 
        my qq num is 49000448.
        not 4900000448.
        [root@oldboy test]# egrep "0{3,}" oldboy.txt 
        my qq num is 49000448.
        not 4900000448.
        [root@oldboy test]# egrep "0{3}" oldboy.txt 
        my qq num is 49000448.
        not 4900000448.
        [root@oldboy test]# egrep "0{,3}" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        :::
        ///
        :d::f
        /etc/oldboy//
        

        1.6 扩展正则测试题:

        测试题:

        1.过滤/etc/passwd中含有root或oldboy的行。

         grep -E "root|oldboy" /etc/passwd
        

        2.过滤/etc/passwd中至少含有1个0字符串的行。

        egrep "0+" /etc/passwd
        

        3.过滤/etc/passwd中匹配o字符0次或1次的行。

        egrep "o?" /etc/passwd
        

        4.过滤/etc/passwd中匹配0字符1次到3次的行。

        egrep "0{1,3}" /etc/passwd
        

        5.过滤/etc/shadow中匹配含有连续多个冒号或斜线的行。

        egrep "[:/]+" /etc/shadow
        

        1.7 【元字符】

        表达式描述
        \b匹配单词边界,例如:\boldboy\b只匹配oldboy单词不匹配oldboy*
        \B匹配非单词的边界例如:oldboy\B 匹配oldboy123中的oldboy,不匹配单独的oldboy单词
        \w匹配字母、数字与下划线,等价[_[:alnum:]]
        \W匹配字母、数字与下划线以外的字符,等价[^_[:alnum:]]
        \d匹配单个数字字符,注意,这个表达式需要使用grep -P参数才能识别*
        \D匹配单个非数字字符,注意,这个表达式需要使用grep -P参数才能识别
        \s匹配1位空白字符,注意,这个表达式需要使用grep -P参数才能识别
        \S匹配1位非空白字符,注意,这个表达式需要使用grep -P参数才能识别

        测试:

        [root@oldboy test]# egrep "oldboy\b" /etc/passwd
        oldboy:x:5023:5023::/home/oldboy:/bin/bash
        [root@oldboy test]# 
        [root@oldboy test]# egrep "\boldboy\b" /etc/passwd
        oldboy:x:5023:5023::/home/oldboy:/bin/bash
        [root@oldboy test]# egrep -w "oldboy" /etc/passwd
        oldboy:x:5023:5023::/home/oldboy:/bin/bash
        

        1.8 特殊预定义表达式

        正则表达式描述示例
        [:alnum:]匹配任意一个字母或数字字符,相当于[a-zA-Z0-9][[:alnum:]]
        [:alpha:]匹配任意一个大小写字母字符,相当于[a-zA-Z][[:alpha:]]
        [:blank:]空格与制表符(横向和纵向)[[:blank:]]
        [:digit:]匹配任意一个数字字符,相当于[0-9][[:digit:]]
        [:lower:]匹配小写字母,相当于[a-z][[:lower:]]
        [:upper:]匹配大写字母,相当于[A-Z][[:upper:]]
        [:punct:]匹配标点符号[[:punct:]]
        [:space:]匹配一个包括换行符、回车等在内的所有空白符[[:space:]]
        [:graph:]匹配任何一个可以看得见的且可以打印的字符[[:graph:]]
        [:xdigit:]任何一个十六进制数(即:0-9,a-f,A-F)[[:xdigit:]]
        [:cntrl:]任何一个控制字符(ASCII字符集中的前32个字符)[[:cntrl:]]
        [:print:]任何一个可以打印的字符[[:print:]]
        [root@oldboy test]# egrep "[[:alnum:]]" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        :d::f
        /etc/oldboy//
        [root@oldboy test]# egrep "[[:alpha:]]" oldboy.txt 
        I am oldboy teacher!
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        our site is http://www.oldboyedu.com
        my qq num is 49000448.
        not 4900000448.
        my god ,i am not oldbey,but OLDBOY!
        :d::f
        /etc/oldboy//
        [root@oldboy test]# egrep "[[:digit:]]" oldboy.txt 
        my qq num is 49000448.
        not 4900000448.
        

        -A after 显示过滤的字符串和它之后的多少行

        -B before 显示过滤的字符串和它之前的多少行

        -C context 显示过滤的字符串和它之前之后的多少行

        [root@oldboy test]# grep -A 3 5 b.txt 
        5
        6
        7
        8
        [root@oldboy test]# grep -B 3 5 b.txt 
        2
        3
        4
        5
        [root@oldboy test]# grep -C 3 5 b.txt 
        2
        3
        4
        5
        6
        7
        8
        

        2. Sed命令语法及参数说明

        Sed是Stream Editor(字符流编辑器)的缩写,简称流编辑器。

        Sed是操作、过滤和转换文本内容的强大工具。常用功能有对文件实现快速增删改查(增加、删除、修改、查询),其中查询的功能中最常用的2大功能是过滤(过滤指定字符串)和取行(取出指定行)。

        取行和替换*****

        【语法格式】

        sed [选项] [sed内置命令字符] [输入文件]

        options[选项] 解释说明(带※的为重点)

        -n 取消默认sed的输出,常与sed内置命令的p连用※

        输出想要的内容。

        -i 直接修改文件内容,而不是输出到终端。

        -e 允许多次编辑

        p 全拼print,表示打印匹配行的内容,通常p会与选项-n一起使用※

        [root@oldboy test]# cat -n oldboy.txt 
             1	I am oldboy teacher!
             2	I teach linux.
             3	
             4	I like badminton ball ,billiard ball and chinese chess!
             5	our site is http://www.oldboyedu.com
             6	my qq num is 49000448.
             7	
             8	not 4900000448.
             9	my god ,i am not oldbey,but OLDBOY!
            10	:::
            11	///
            12	:d::f
            13	/etc/oldboy//
        

        练习:取oldboy.txt 2-4行

        sed -n '2,4p' oldboy.txt
        [root@oldboy test]# sed -n '2,4p' oldboy.txt
        I teach linux.
        I like badminton ball ,billiard ball and chinese chess!
        

        取第4行

        [root@oldboy test]# sed -n '4p' oldboy.txt
        I like badminton ball ,billiard ball and chinese chess!
        笔试至少5个答案
        

        问题2:过滤出含有oldboy字符串的行※。

        sed -n ‘//p’ #框架化

        方法1:

        [root@oldboy test]# grep oldboy oldboy.txt 
        I am oldboy teacher!
        our site is http://www.oldboyedu.com
        /etc/oldboy//
        

        方法2:

        [root@oldboy test]# sed -n '/oldboy/p' oldboy.txt 
        I am oldboy teacher!
        our site is http://www.oldboyedu.com
        /etc/oldboy//