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

原文地址:https://www.cnblogs.com/kebibuluan/p/9362355.html