简介:正则表达式在查找中的作用是非常重要的。本课程是《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/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinuucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologingopher:x:13:30:gopher:/var/gopher:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologinvcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologinsaslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologinpostfix:x:89:89::/var/spool/postfix:/sbin/nologinsshd: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:0bin:1daemon:2adm:3lp:4sync:5shutdown:6halt:7mail:8uucp:10operator:11games:12gopher:13ftp:14nobody:99vcsa:69saslauth:499postfix:89sshd: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 "%"
1207接下来介绍下printf和print的区别,printf打印输出需要加上\n
[root@localhost ~]# awk '{print $2 "\t" $4}' student.sh
weiyuan 60
xiaoming 70
awk打印输出student.sh中的第2和4列的数据
接下来:接受awk中的条件运算符begin和end
begin是在所有的动作执行之前先执行
现在我们来看下面的条件运算符begin
[root@localhost ~]# awk 'BEGIN{print "test"}{print $2 "\t" $4}' student.sh
test
weiyuan 60
xiaoming 70
Begin是一个条件,满足Begin条件就执行动作打印输出test
Begin就是在执行任何动作之前都想执行begin的动作,{print $2 "\t" $4}动作前面没有任何条件,表示就全部执行动作{print $2 "\t" $4}打印第2和4列的数据,所以输出就是上面的
形式
同理还有END
[root@localhost ~]# awk 'END{print "test"}{print $2 "\t" $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 "\t" $3}'
sshd 74
上面grep –v Name 就是将包含Name的行给取出掉
$4获得第4列的数据如果大于70的就执行{printf $2 “\n”}将第2列的数据打印出来
[root@localhost ~]# cat student.sh | grep -v name | awk '$4>=60{printf $2 "\n"}'
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