Skip to content

正则表达式

用途

对于一些匹配字符串的操作,如果我们使用C++语言,就会非常麻烦。

此时使用正则表达式写个脚本就会非常简单,极大的减少工作量。

比如登录界面匹配用户名,密码,使用正则表达式判断是否符合基本规范就会非常简单。

在C++程序中嵌入其它语言写的程序在网络编程部分会提到的,这是一个非常重要的模块。

例如, 在读取日志文件时,日志文件常常非常大,50g以上,此时vim就失去了效果,因为使用vim打开日志文件会将文件加载到内存中,导致内存溢出,程序崩溃。

此时我们用正则表达式选取我们需要的内容就会非常方便,因为日志文件都是非常规律的,正好正则表达式发挥。

大多数脚本语言都已经包含了正则表达式,这些脚本语言本身就可以对字符串方便的进行匹配。

正则表达式的符号

基础正则:^, $, ., *, []

扩展正则:+, |, (), {}, ?

基础正则是正则表达式诞生时就有的,扩展正则是正则表达式在后续发展进程中逐渐加入的。

' '" "

' '" "表示整体。正则表达式一定要用' '" "扩起来,否则极其容易出现错误。

正则表达式中,' '" "没有区别,但在某些语言中," "会带来各种各样的错误,比如perl,php和接下来要讲的awk,awk可以算作一种语言。

grep命令

介绍

在文件中匹配字符串,然后把满足条件的行打印出来。

常用参数

grep的参数非常多,但常用的就三个。

  • -i:ignore的简写,表示忽略字母的大小写。
  • -v:invert的简写,表示输出文件未被匹配的行。
  • -n:number的简写,表示输出文件的行号。

使用示例

  • grep -n int test.cpp 在test.cpp文件找到包含int的行 -n表示行号
  • grep -nv int test.cpp 在test.cpp文件找到不包含int的行 -n表示行号

基础正则

^$^$.*.*[]
以...开头以...结尾空行任意字符前一个字符连续出现0次及以上所有行括号中的任意一个

讲一下正则的贪婪性,对于正则表达式,在表示连续出现时,会匹配尽量多的字符串。

[0-9]表示任意数字,[a-z]表示任意小写字母。[a-zA-Z]表示任意大小写字母

注意:中括号中的特殊字符将不会被当做特殊字符处理

扩展正则

  • +:表示前面的符号出现了至少一次

  • |:表示或者,和[]的区别就是|匹配的是单词,而[]匹配的是单个字符

  • ():被()括起来的字符串。会被解释为一个整体。

  • {m, n}:表示前面的字符连续出现了m到n次

  • ?:表示前一个字符出现0次或1次

常用范例

这里主要是讲几个比较常用的转义字符。

  • \s: 表示任意多个空格字符(包括空格和\t)
  • \S: 表示不是空白的字符
  • \w: 表示[0-9A-Za-z_],\w就是个简写
  • \W: 和\w相反,表示不是[0-9A-Za-z]的字符
  • \b: 表示单词的结束(注意,\b并不占据位置进行匹配,它只检测接下来的字符是否为\w)

注意:还有一个比较常用的转义字符\d,代表[0-9]。但是grep命令并不支持,这个转义字符在perl语言中是支持的。

对于运维人员来说,有时需要写一些比较复杂的正则表达式。比如email格式,url格式,xml格式这些。我们开发人员只需要掌握一些简单的正则表达式就可以了,其实正则表达式不会很难,最多只是长一些罢了。

如果大家想要练习自己的正则表达式水平,直接百度:常见的正则表达式范例,没事干多看一看,积累一下就可以了。

sed命令

解释

对文件按行进行遍历,依次对这些行进行操作。sed就是stream editor的简写,意为对每一行以流的形式进行处理。

执行过程

sed的执行过程很简单,就是每次向进程中加载一行。如果对这一行没有任何修改,则直接将这一行输出,使用-n参数可以不输出未经修改的行。

功能

增加 三种标识符 c:替代(replace)

sh
sed -r 's/old_text/new_text/' filename.txt

a:追加:(append)在下一行追加

sh
sed '/pattern/a\This is an appended line.' filename.txt

i:插入:(insert)在上一行插入

sh
sed '/pattern/i\This is an inserted line.' filename.txt

增加部分总结:这部分用的比较少,但还是应该尽量掌握。

删除 标识符为d

按照行数删除

sh
sed -r '1,3d' num.txt # 删除1到3行 其余输出出来

按照范围删除

sh
sed -r '/2022-01-01 10:10:00/,/2022-01-01 10:10:10/d' num.txt

这部分用的比较少,尽量掌握就可以了。

修改 标识符为s 基础用法

sh
sed 's/old_text/new_text/' filename.txt

s配合"()"的用法

sh
sed -r 's/(pattern)/replacement/g' filename.txt

这部分非常常用。尤其在处理一些规律性的文本时更是极其方便,一定要会。

查找 标识符为p 按照行数查找:

sh
sed -n '1,10p' num.txt # 输出1到10行

按照内容查找

sh
sed -n '/pattern/p' filename.txt

查找部分最重要的就是按照内容查找,日志文件中经常使用,//中是可以支持正则表达式的,但一般这里用不到正则表达式。

awk命令

介绍

(1)awk是一种语言,它有一套完整的语法,内容十分丰富的,有专门的书去系统的讲awk。专门买一本书去学awk是完全没有意义的,我们只要会一些基本的操作就可以完成基本任务了,如果有需要,可以遇到问题再去积累,这样效率远比看书高。 (2)awk的名字源于发明这门语言的三个人的名字。这点了解一下就可以了。

执行过程

  • 先执行BEGIN指令
  • 判断每行是否满足条件,若满足条件,进行操作。
  • 最后执行END指令
sh
awk -F: 'BEGIN{print "this is BEGIN"}NR==1{print $1}END{print "this is END"}' num.txt

任意一个部分都可以省略,条件判断部分也可以省略。

注意:这里的NR为number of record的简写,在awk中,record也表示行的含义,直接翻译过来就是记录。

$ n表示第n行,$0表示全行,$NF代表最后一行

常用的参数

(1) -F可以设置选取列时的分隔符,默认为\s (2) -v OFS=可以设置显示的列的分隔符,默认为空格

sh
awk -F: -v OFS=: '{print $1,$2,$3,$4}' num.txt

常用内置变量

(1) NR:之前例子中使用的NR就是awk最常用的内置变量。 (2) NF:表示一行的最后一列,nember of field的简写,在awk中field表示列、

判断条件:

  • NR进行条件判断,可以使用,&&||
  • 可以使用传统的//判断范围
sh
awk -F: '/2022-01-01 10:10:00/,/2022-01-01 10:10:10/' num.txt
  • 可以对某一列单独进行处理,这个用法很重要,弥补了grep的不足
sh
awk -F: '$5~/^s/' num.txt # 打印每一行第五列若满足什么则打印出来

BEGIN和END的用法:

(1) awk是一门语言,一门语言是可以计算的。 (2) BEGIN用的相对比较少,BEGIN可以定义变量,进行不涉及文件的统计,但awk一般只进行简单的操作,这部分用的比较少。 (3) END用的就比较多了,因为我们经常在END中计算,然后输出结果。

  • 统计文件有多少行
sh
awk '{sum++}END{print sum}' num.txt
  • 统计某一列的和
sh
awk '{sum+=$4}END{print sum}' num.txt #每一行第四列

总结一下awk命令:awk是一种语言,严格来说,awk的功能其实非常多,但一般来说,这些操作就够用了,再复杂的操作就不适用awk来完成了。

总结

  • grep擅长过滤,命令格式最简单方便。
  • sed擅长按行的形式进行处理,比如范围过滤,替换,增加,删除。
  • awk删除对列进行过滤,计算,对比等操作。
  • 从命令的复杂程度考虑,awk > sed > grep。
  • 所以我们一般优先考虑grep,然后是sed,再之后是awk。
  • 我们以后在处理文件时,要合理的使用这三个命名,这三个命令很常用,也很重要。