Linux之正则表达式的应用

时间:2024-03-28 10:00:43

正则表达式作为Linux入门的重要符号语言,是基础中的基础,当然,也是初学者人人头疼的一座山。在此略做小结,如果有幸帮了哪位入门同仁的困惑,也算不枉此篇。

此篇举例仅基于grep或egrep进行,一来刚学习至此,二来尽求此点清晰全面。本文重点问讲解如何使用正则表达式,毕竟解决问题是目的。行文或有不周之处,还望各位赐教。

在这之前,我们先来简要回顾下grep的用法。


grep -[acinv]      

--color=auto 将匹配的结果着色显示
-v 反向匹配
-i 忽略大小写
-n 显示的结果前增加行号
-c 仅显示匹配到结果的行的数量
-b 在输出结果前打印当前行在输入中的字符偏移量
-o  仅显示最后正则表达式匹配到的字符串
-q 静默模式,不输出任何信息,此作用等同于&> /dev/null
-A # 显示关键字行及向后#行(#为数字)
-B #

显示关键字行及向前#行

nmap -v -sP 172.17.252.0/24 |grep-B1 "Host is up"|grep for |cut -d" " -f5 |wc -l

(扫描IP段,并统计在线IP数量)

-C # 显示关键字向前#行,当前行,及向后#行
-e

e 关键字1 -e 关键字2  实现多个选项间的逻辑or关系

grep -e 'cat' -e 'dog' file(显示有cat或dog的行)

-w 匹配整个单词,即基于单词过滤
-E

使用扩展正则表达式 或egrep

扩展的正则表达式egrep 或grep -E支持无转移字符\,但指范围时还需要表示为\<\>、\b\b等

-F 不使用正则表达式 或 fgrep

——更多grep选项请到http://os.51cto.com/art/201108/285119.htm


下面是一些正则表达式的简单介绍。


1.字符匹配

. 匹配任意单个字符
[] 匹配指定范围内的任意单个字符
[^] 匹配指定范围外的任意单个字符
[:alnum:] 字母和数字,或[0-9a-zA-Z]
[:alpha:] 代表任何英文大小写字符,亦即[a-zA-Z]
[:upper:] 大写字母,或[A-Z]
[:lower:] 小写字母,或[a-z]
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字 [0-9]
[:xdigit:] 十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号


2.匹配次数

匹配前面的字符任意次,包括0次
.* 任意长度的任意字符
\? 匹配其前面的字符0或1次
\+ 匹配其前面的字符至少1次
\{n\} 匹配前面的字符n次
\{m,n\} 匹配前面的字符至少m次,至多n次
\{,n\} 匹配前面的字符至多n次
\{n,\} 匹配前面的字符至少n次


3.位置锚定

^ 行首锚定,用于模式的最左侧
$ 行尾锚定,用于模式的最右侧
^PATTERN$ 用于模式匹配整行
^$ 空行
^[[:space:]]*$ 空白行
\< 或 \b 词首锚定,用于单词模式的左侧(无需与下面的左右同时引用)
\> 或 \b 词尾锚定;用于单词模式的右侧
\<PATTERN\> 匹配整个单词 或\bPATTERN\b


4.分组

\(\)

将一个或多个捆绑在一起,当作一个整体进行处理,如:\(Gintoki\)\+

分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为:\1,\2,\3,....

\1表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

示例:\(saber\+\(archer\)*\)

   \1:saber\+(archer\)*

   \2:archer

后项引用

引用前面的分组括号中的模式所匹配字符,而非模式本身。即引用的为实际字符,不是可变的变

示例:添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名同shell名的行

cat /etc/passwd | grep "\(^.*\)\>.*\/\1$"

Linux之正则表达式的应用

或:\| 示例:s\|a:a或b  C\|cat:C或cat  \(C\|c\)at:Cat或cat


5.常配合使用的相关命令     

sort

排序。默认数字从小到大,字符从A-z

 -r 执行反方向(由上至下)整理(Z-a,数字从大到小)

        -n 执行按数字大小整理

        -f 选项忽略(fold)字符串中的字符大小写

        -u 选项(独特,unique)删除输出中的重复行

        -t c 选项使用c做为字段界定符

        -k X 选项按照使用c字符分隔的X列来整理能够使用多次

head 头显示

-n #(#为数字)显示前#行

-c # 显示前#个字节

tail 尾显示

-n # 显示后#行

-c # 显示后#个字节

tr 转换和删除字符

-s '' 把连续重复的字符取一个表示

-d '' 删除''内所有字符

 -t '' '' 第一个字符集对应字符转化为第二字符集

        tr -t 'A-Z' '1-9'不加-t时第9-26个字符都转化为9,-t保持原形

-c '' 反向,即只保留''内字符

   

热身完毕,接下来我们冲个凉(来看看一些经常用到的命令)。

1、找出ifconfig “网卡名”命令结果中本机的IPv4地址(head -n 2为截取输出前两行,tail -n 1为截取输出最后一行,tr -s " "为将连续的多个空格保留为一个,cut -d: -f3为以列截取,以:为间隔截取第四列;这里我们只取了第一个IP,下面有个题目取出所有IPv4的IP地址的)

[[email protected] ~]# ifconfig |head -n 2 |tail -n 1|tr -s " " : |cut -d: -f3
172.17.252.90

Linux之正则表达式的应用

2、查出分区空间使用率的最大百分比值(df显示分区信息,tr -s ' ' %为将所有的连续空格保留一个,并将其替换为%,sort -t% -k5 -n以%为间隔符,按第5列数字大小排序;如果不用%替换空格,那么得到结果17%后还需进一步截取)

[[email protected] ~]# df|tr -s ' ' %|sort -t% -k5 -n|tail -n 1|cut -d% -f5

17

Linux之正则表达式的应用

3、查出用户UID最大值的用户名、UID及shell类型

cat /etc/passwd |cut -d: -f1,3,7|sort -n -t : -k 2|tail -n 1

4、查出/tmp的权限,以数字方式显示(stat file查看文件时间戳)

stat /tmp| head -n 4|tail -n1|cut -d/ -f1|cut -d'(' -f2

stat -c %a /tmp/

stat /tmp|head -n 4|tail -n1|tr -dc [1-7];echo -e '\n

5、统计当前连接本机的每个远程主机IP的连接数,并按从大到小排序

netstat -tun | grep ESTAB|tr -s " " : |cut -d: -f6 |sort -nr |uniq -c

 

下面的题目可以练练手。答案没有唯一之说,不管什么方法,能够曲径通幽达到解决问题的目的就好。当然,也多的执行步骤也就意味着越多的风险。化繁为简,精洁高效,那样也就好了。

 

Part 1

1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两

种方法)

  cat /proc/meminfo |grep ^'\(S\|s\)'

  cat /proc/meminfo |grep ^[Ss]

  cat /proc/meminfo |grep -i "^s"

  cat /proc/meminfo|grep -e ^s -e ^S

  cat /proc/meminfo|grep "^s\|^S"

  cat /proc/meminfo|grep "^[s\|S]"

2、显示/etc/passwd文件中不以/bin/bash结尾的行

  cat /etc/passwd |grep -v '/bin/bash$'

  grep -v "/bin/bash$" /etc/passwd

3、显示用户rpc默认的shell程序

  cat /etc/passwd |grep ^'\<rpc\>'|cut -d: -f7

  grep -w "^rpc"  /etc/passwd  | cut -d : -f7

4、找出/etc/passwd中的两位或三位数

  cat /etc/passwd | grep '\<[0-9]\{2,3\}\>' 突出显示,没有取出数字,实际上不符合题意

  cat /etc/passwd |grep -o "\<[0-9]\{2,3\}\>"只取出数字

5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面存非空白字符的行

  cat /etc/grub2.cfg  |grep"^[[:space:]]\+[^[:space:]]"

6、找出“netstat -tan”命令的结果中以‘LISTEN’后跟任意多个空白字符结尾的行

  netstat -tan|grep "\<LISTEN\>[[:space:]]*$"

7、显示CentOS7上所有系统用户的用户名和UID

  cat /etc/passwd |cut -d: -f1,3|grep '\<[0-9]\{1,3\}\>$' 

8、利用df和grep,取出磁盘各分区利用率,并从大到小排序

  df |grep ^/dev/sd |grep -o "\b[[:digit:]]\{1,3\}\b%"|sort-rn

 

Part 2

 1、显示三个用户root、mage、wang的UID和默认shell

  cat /etc/passwd |cut -d: -f3,7 |egrep^'\<mage\>|\<root\>|\<wang\>'

  cat /etc/passwd|grep -E "^(root|wang|mage)\>"|cut -d :-f3,7

  cat /etc/passwd|grep -E -w "^(root|wang|mage)"|cut -d :-f3,7

2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行

  cat /etc/rc.d/init.d/functions |grep '^[_[:alpha:]]*[(]'

3、使用egrep取出/etc/rc.d/init.d/functions中其基名

  echo /etc/rc.d/init.d/functions|egrep -o \([[:alpha:]]\)+$

4、使用egrep取出上面路径的目录名(这个题目开始我是想用)

 echo /etc/rc.d/init.d/functions|egrep -o \(^/.*/\) 截取//之间所有字符

  echo /etc/rc.d/init.d/functions|egrep -o \(^/.+/\) 以/开始,以/结束

  echo /etc/rc.d/init.d/functions|egrep -o \(.+/\) 以任意字符开始,以/结束

5、统计last命令中以root登录的每个主机IP地址登录次数

  last|egrep root.*[.]|tr -s ' '|cut -d' ' -f3|sort |uniq -c

6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255

  echo {0..300}|egrep -o "\<[0-9]{,1}\>"

  echo {0..300}|egrep -o "\<[0-9]{2}\>"

  echo {0..300}|egrep -o "\<1[0-9]{2}\>"

  echo {0..300}|egrep -o "\<2[0-4][0-9]\>"

  echo {0..300}|egrep -o "\<25[0-5]\>"

7、显示ifconfig命令结果中所有IPv4地址

  ifconfig |egrep [.].*[.]|tr -d [:alpha:]

8、将此字符串:welcome to magedu linux 中的每个字符

去重并排序,重复次数多的排到前面

  echo "welcome to magedu linux "|egrep -o .|sort |uniq -c|sort -r

  echo /etc/rc.d/init.d/functions|egrep -w \([[:alpha:]]\)+$

 














本文转自阿拉杜美美51CTO博客,原文链接:http://blog.51cto.com/amelie/1951971 ,如需转载请自行联系原作者