• shell编程之正则表达式


    简介:正则表达式在查找中的作用是非常重要的。本课程是《Tony老师聊shell》系列课程的第四篇,为你带来Linux shell中的正则表达式,字符截取命令cut、printf、awk和sed,字符处理命令sort和wc。

    *匹配多个字符

    ?匹配一个字符

    []匹配括号中的一个字符

     注意a*是匹配所有的内容显示所有的内容,所有这里没有实际的意义一定要注意

    我们举个例子来看

    Dd.sh

    a

    aa

    aaa

    aaaa

    aaaaa

    b

    bb

    bbb

    [root@localhost ~]# grep "a*" dd.sh

    a

    aa

    aaa

    aaaa

    aaaaa

    b

    bb

    bbb

    显示全部的内容

    查询包涵至少一个a字母的

    [root@localhost ~]# grep "aa*" dd.sh

    a

    aa

    aaa

    aaaa

    aaaaa

    查询至少包涵两个aa字母的

    [root@localhost ~]# grep "aaa*" dd.sh

    aa

    aaa

    aaaa

    aaaaa

    我们举例来分析

    ee.sh

    sood

    siid

    sjjd

    sjjjd

    sjjjjd

    sjjjjjjjd

    [root@localhost ~]# grep "s..d" ee.sh

    sood

    siid

    sjjd

    [root@localhost ~]# grep "s.*d" ee.sh

    sood

    siid

    sjjd

    sjjjd

    sjjjjd

    sjjjjjjjd

    [root@localhost ~]# grep ".*" ee.sh

    sood

    siid

    sjjd

    sjjjd

    sjjjjd

    sjjjjjjjd

    [root@localhost ~]#

    只要每行的数据中包含0-9中的任意一个数字,该行都会被匹配出来

    .本来的意思是匹配任意一个字符。现在加上转义符号之后就取消.的作用,表示以.结尾行

    接下来就是本章的重点内容

    Ff.sh

    aa

    aaa

    aaa

    aaaaa

    aaaaaa

    aaaaaaa

    [root@localhost ~]# grep "a{3}" ff.sh

    aaa

    aaa

    aaaaa

    aaaaaa

    aaaaaaa

    我们可以看到上面把多个联系包涵aaa的字符都全部匹配出来了,如果仅仅匹配只包涵三个aaa的,我们就需要前后添加限定字符的形式来解决,

    这个就表示在x和字母u之间连续出现三次c的行的匹配出来

    同理上面的匹配,最好也要采用前后字符进行限定

    匹配在x和字母u之前。字母c联系出现2次或者三次

    总结:使用上面的字母匹配的时候,一定要在前面和后面加上字母进行限定才有效果,例如上面的匹配在x和字母u之前。字母c联系出现2次或者三次

    接下来我们来介绍cut命令

       正如其名,cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut是以每一行为一个处理对象的,这种机制和sed是一样的。

    cut是对行内容进行操作的,行间分隔符为制表符Tab,cut的默认分割符是Tab制表符 

    我们来看下面的操作

    ( 行间分隔符为制表符Tab,cut的默认分割符是制表符 )

        

      

      

    [root@localhost ~]# cat /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
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
    operator:x:11:0:operator:/root:/sbin/nologin
    games:x:12:100:games:/usr/games:/sbin/nologin
    gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    nobody:x:99:99:Nobody:/:/sbin/nologin
    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
    saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

    我们可以看到etc/passwd是安装:进行分割的,我们可以使用-d指定分隔符

      提取系统的用户名和uid:

        cut -d ":" -f 1,3 /etc/passwd

    [root@localhost ~]# cut -d ":" -f 1,3 /etc/passwd
    root:0
    bin:1
    daemon:2
    adm:3
    lp:4
    sync:5
    shutdown:6
    halt:7
    mail:8
    uucp:10
    operator:11
    games:12
    gopher:13
    ftp:14
    nobody:99
    vcsa:69
    saslauth:499
    postfix:89
    sshd:74

      与grep组合使用:( 假设批量添加100个普通用户,或需要批量删除,那么需要提取普通用户的名字 )

        useradd user1

        useradd user2

        useradd user3

       ( 所有系统用户登录目录都是/sbin/nologin , 通过匹配/bin/bash 提取所有能登录的用户 , -v 取反选择不包含root的行,再用cut匹配列提取用户名;把结果赋给变量,通过循环删除 )

        cat /etc/passwd | grep "/bin/bash" | grep -v "root" | cut -d ":" -f 1

    我们来解释下上面的命令

    grep "/bin/bash" /etc/passwd | grep -v "root"

    首先grep "/bin/bash" /etc/passwd 查询/etc/passwd包涵/bin/bash的行

    将得到的结果最为grep -v "root"的查询初始值,grep –v就是查询初始值中不包涵root的行

    Cut –f 1 –d “:”

    提取第一列中的值,制定提取默认的分隔符是”:”,默认分隔符是tab

    Cut命令只能提取一些简单的操作,满足有条件分割的就使用cut,例如规则的使用tab或者:等进行分割的,如果不规则的分割例如空格等如果要使用复杂的命令,要使用awk命令

    例如我们要获得use列的值,是按照空格不规则分割的使用cut是无法获得的,只能使用awk的方式

    Awk也是在文件中进行匹配操作,满足条件1执行动作1,满足条件2执行动作2。

    上面就打印student.txt中的第2列和第4列的数据,因为动作{}之前没有写条件,就默认条件满足就直接执行动作printf将第2列和第4列的数据打印出来

    接下来我们看这样的一个案例,cut无法执行,只能使用awk来解决

    [root@localhost ~]# df -h

    Filesystem                    Size  Used Avail Use% Mounted on

    /dev/mapper/VolGroup-lv_root   19G  2.0G   16G  12% /

    tmpfs                         250M     0  250M   0% /dev/shm

    /dev/sda1                     485M   31M  429M   7% /boot

    [root@localhost ~]#

    我们来获得第5列Use%的信息,使用cut通过各种方式都无法获得

    这个时候只能使用awk,对于有规则的风格的可以使用cut,如果cut没有作业,就只能使用awk

    [root@localhost ~]# df -h | awk '{print $5}'

    Use%

    12%

    0%

    7%

    [root@localhost ~]#

    这个时候我们要要获得12%前面的数值12,就可以是cut,指定分割符号是%

    [root@localhost ~]# df -h | awk '{print $5}' | cut -f 1 -d "%"

    Use

    12

    0

    7

     如果要把use去掉可以使用grep -v use 获得不包涵use的行

    [root@localhost ~]# df -h |grep -v 'Use'| awk '{print $5}' | cut -f 1 -d "%"
    12
    0
    7

    接下来介绍下printf和print的区别,printf打印输出需要加上

    [root@localhost ~]# awk '{print $2 " " $4}' student.sh

    weiyuan 60

    xiaoming        70

    awk打印输出student.sh中的第24列的数据

    接下来:接受awk中的条件运算符begin和end

    begin是在所有的动作执行之前先执行

    现在我们来看下面的条件运算符begin

    [root@localhost ~]# awk 'BEGIN{print "test"}{print $2 " " $4}' student.sh

    test

    weiyuan 60

    xiaoming        70

    Begin是一个条件,满足Begin条件就执行动作打印输出test

    Begin就是在执行任何动作之前都想执行begin的动作,{print $2 " " $4}动作前面没有任何条件,表示就全部执行动作{print $2 " " $4}打印第2和4列的数据,所以输出就是上面的

    形式

    同理还有END

    [root@localhost ~]# awk 'END{print "test"}{print $2 " " $4}' student.sh

    weiyuan 60

    xiaoming        70

    test

     案例2:

    接下面我们来看看begin的功能,awk默认是按照tab或者空格进行分割的,现在在/etc/password是按照:进行分割的,我们就可以

    使用begin指定在执行任何动作之前都先执行begin的动作,我们可以在动作中指定分割符号是:

    [root@localhost ~]# cat /etc/passwd | grep 'sshd'  | awk 'BEGIN{FS=":"}{print $1 " " $3}'

    sshd    74

     

    上面grep –v Name 就是将包含Name的行给取出掉

    $4获得第4列的数据如果大于70的就执行{printf $2 “ ”}将第2列的数据打印出来

    [root@localhost ~]# cat  student.sh | grep -v name | awk '$4>=60{printf $2 " "}'

    weiyuan

    xiaoming

    [root@localhost ~]#

    接下来我们重点介绍下sed操作

    sed和vim工具的功能比较类似,主要是对文件的内容进行修改,这里特别要强调一个选项

    -i如果没有-i,虽然屏幕的输出发生了变化,但是文件的内容实际上没有发生变化,例如要删除一行,虽然屏幕上输出是删除了,但是实际上文件的内容是没有删除的

    我们接下来看实际的案例:

    这里查看第2行的内容,要将-n选项添加上,-n表示表示只会把sed处理之后的行内容输出到屏幕上,如果不添加会显示文件的全部内容

    如果要删除文件本身的内容需要添加上-i

    添加操作

    体会操作c是替换一行,s是替换字符

    把第4行的全部的70分全部替换成100分,其中-g表示全部替换,但是因为没有加上-i,没有修改原始文件的内容

    [root@localhost ~]# sort /etc/passwd

    adm:x:3:4:adm:/var/adm:/sbin/nologin

    bin:x:1:1:bin:/bin:/sbin/nologin

    daemon:x:2:2:daemon:/sbin:/sbin/nologin

    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

    games:x:12:100:games:/usr/games:/sbin/nologin

    gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

    halt:x:7:0:halt:/sbin:/sbin/halt

    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

    nobody:x:99:99:Nobody:/:/sbin/nologin

    operator:x:11:0:operator:/root:/sbin/nologin

    postfix:x:89:89::/var/spool/postfix:/sbin/nologin

    root:x:0:0:root:/root:/bin/bash

    saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin

    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

    sync:x:5:0:sync:/sbin:/bin/sync

    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

    按照字母abcd顺序进行排序

    加上-r之后按照字母进行反顺利排序

    [root@localhost ~]# sort -r /etc/passwd

    按照z...ba排序

    可以看到行

    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

    第三个字段是数字,我们要按照第三个字段的数组进行排序如何解决了

    第一获得第三个字段,每个字段按照分隔符:来进行分割获得,首先使用-t指定分隔符

    第二:排序默认是按照字符串,现在要将字符串转换成数字,按照数值进行排序,使用-n指定将字符串转换成数值

    第三:只使用第三个字段排序,那么就是第三个字段是开始字段,第三个字段也是结束字段,使用-k进行指定

    [root@localhost ~]# sort -n -t ":" -k 3,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

    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    halt:x:7:0:halt:/sbin:/sbin/halt

    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

    operator:x:11:0:operator:/root:/sbin/nologin

    games:x:12:100:games:/usr/games:/sbin/nologin

    gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

    postfix:x:89:89::/var/spool/postfix:/sbin/nologin

    nobody:x:99:99:Nobody:/:/sbin/nologin

    saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin

  • 相关阅读:
    [Luogu] P3258 [JLOI2014]松鼠的新家
    [Luogu] P3701 「伪模板」主席树
    [USACO] 打井 Watering Hole
    [Luogu] P3225 [HNOI2012]矿场搭建
    [USACO06JAN] 冗余路径 Redundant Paths
    [Luogu] P1407 [国家集训队]稳定婚姻
    [USACO06JAN] 牛的舞会 The Cow Prom
    [Luogu] P4254 [JSOI2008]Blue Mary开公司
    [Luogu] P1993 小K的农场
    [Luogu] P2279 [HNOI2003]消防局的设立
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/9362355.html
Copyright © 2020-2023  润新知