0. 前言
在日常的文本处理过程中,为准确、高效的工作,正则表达式是必备技能之一。下面,我将用尽可能通俗、简单的语言将其尽可能全面的总结。
1. 通配符glob
所谓通配符glob,既是用特定的字符(通常称之为元字符),可实现对相关文件名进行匹配,实现已用多个文件的功能。详细介绍可查看帮助:man 7 glob
通配符相关的元字符如下:
*: 匹配任意长度的任意字符;例如,p*可匹配p开头的的所有文件。
?: 匹任意单个字符;例如,p?可匹配p后面出现单个字符的文件,例如pi.
[]: 中括号匹配指定的集合内的任意单个字符
例如:
[wang]:表示w,a,n,g四个字符中的任意一个。
[0-9]:匹配单个字符
[[:upper:]]:匹配任意单个所有大写字母
[[:lower:]]:匹配任意单个所有小写字母
[[:digit:]]:匹配任意单个所有数字,等价于[0-9]
[[:alpha:]]:匹配任意单个所有字母
[[:alnum:]]:匹配任意单个所有字母和数字
[[:space:]]:匹配单个空白字符
[[:punctl:]]:匹配单个标点符号
[^]:匹配指定集合外的任意单个字符
例如:
[^stone] 表示除了s,t,o,n,e以外的其它单个字符
[^a-z] 表示除了小写字母的其他单个字符
NOTE:之所以要提及通配符,是因为Linux相关知识太多,太过分散。导致在学习正则表达式时,总记得有个东西很相似,甚至相同。
实质上,通配符和正则表达式中的元字符是一样的,只是更多的时候,用于文件的查询。
故而,更多的会和ls,find,cp,tar,等linux命令配合使用。
正则表达式用于文本内容的查询,会和grep家族命令,sed,awk配合使用。此外,在vim,less,nginx,mysql,varnish等软件中也会支持
2. 正则表达式
2.1 基本概念
REGEXP:Regular Expression,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字面意义,而表示控制或通配功能
也就是说:为提供方便,提高工作效率,一些字符不表示本来的字符了,例如:a是a,但是在正则表达式中,可能就不表示a了。 这样就会引发两个新的问题:1. 不表示本来的意思,又表示什么呢?上面其实有说了,表示控制或通配。何为控制?何为通配?下文将会讲解 2. 如果我就是想表示字符原本的含义,又该怎么办?
分类:
基本正则表达式:BRE
扩展正则表达式:ERE
二者区别更多的在于表达形式,扩展正则在表达形式上,会比基本正则表达式更加简单。当然,在使用时,也会有一定却别,这也是,平时工作中,很容易犯的一个错误。
元字符分类:字符匹配、匹配次数、位置锚定、分组
只要接触过正则表达式的人,都会知道这四中类型的元字符。可是,就是不会用。其实,当站在正则视角之外,对于文档中某个字符或字符串进行匹配时,除了字符本身,对于同一字符字符出现多次我们不可能去直接写同样的次数,还有可能我们根本就不知道具体的次数,查询的是一个范围,所以才会有匹配次数的元字符。 此外,我们去查询一段字符时,还会对于字符出现在一行中的位置比较关注,故而会有一个对字符的位置进行限定,可能是一行的位置,或者字符在一个单词中的位置,这写都是需要考虑的。 最后,为了提高效率,经常会对于匹配到的一整个字符串进行处理,故而有了,分组。
2.2 字符匹配
. 匹配任意单个字符
[] 匹配指定范围内的任意单个字符,示例: [wang] [0-9] [a-z] [a-zA-Z]
[^] 匹配指定范围外的任意单个字符
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母 [:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字 [:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
2.3次数匹配
用在要指定次数的字符后面,用于指定前面的字符要出现的次数
* 匹配前面的字符任意次,包括0次
贪婪模式:尽可能长的匹配
.* 任意长度的任意字符
\? 匹配其前面的字符0或1次
\+ 匹配其前面的字符至少1次
\{n\} 匹配前面的字符n次
\{m,n\} 匹配前面的字符至少m次,至多n次
\{,n\} 匹配前面的字符至多n次
\{n,\} 匹配前面的字符至少n次
2.4 次数匹配
定位出现的位置
^ 行首锚定,用于模式的最左侧
$ 行尾锚定,用于模式的最右侧
^PATTERN$ 用于模式匹配整行
^$ 空行
^[[:space:]]*$ 空白行
\< 或 \b 词首锚定,用于单词模式的左侧
\> 或 \b 词尾锚定,用于单词模式的右侧
\<PATTERN\> 匹配整个单词
2.5 分组
分组:\(\) 将一个或多个字符捆绑在一起,当作一个整体处理,如: \(root\)\+
分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...
\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符
示例: \(string1\(string2\)\)
\1 : string1\(string2\)
\2 : string2
后向引用:引用前面的分组括号中的模式所匹配字符, 而非模式本身
或者: \|
示例: a\|b a或b
C\|cat C或cat
\(C\|c\)at Cat或cat
2.6 练习
https://www.jianshu.com/p/42f04ee8a61c
3. 扩展正则表达式
3.1 字符匹配
. 任意单个字符
[] 指定范围的字符
[^] 不在指定范围的字符
3.2 次数匹配
* 匹配前面字符任意次
? 0或1次
+ 1次或多次
{m} 匹配m次
{m,n} 至少m,至多n次
3.3 位置锚定
^ 行首
$ 行尾
\<, \b 语首
\>, \b 语尾
3.4 分组
()
后向引用:
\1, \2, ...
或者:
a|b a或b
C|cat C或cat
(C|c)at Cat或cat
3.5 练习
https://www.jianshu.com/p/851e51116a08
4. 文本处理三剑客
grep:文本过滤(模式:pattern)工具
grep,egrep,fgrep(不支持正则表达式搜索)
sed:stream editor,文本编辑工具
awk:Linux上的实现gawk,文本报告生成器
4.1 grep
grep:Global search REgular expression and Print out the line
作用:文本搜索工具,根据用户指定的“模式”对目标逐行进行匹配检查:打印匹配到的行.
语法格式:
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
PATTERN:
由正则表达式字符及文本字符所编写的过滤条件
OPTIONS:
--color=auto: 对匹配到的文字着色显示
-m # 匹配#次后停止
-v 显示不被pattern匹配到的行
-i 忽略字符大小写
-n 显示匹配的行号
-c 统计匹配的行数
-o 仅显示匹配到的字符串
-q 静默模式,不输出任何信息
-A # after,后#行
-B # before,前#行
-C # context,前后各#行
-e 实现多个选项间的逻辑or关系
grep -e 'cat' -e 'dog' file
-w 匹配整个单词
-E 使用ERE
-F 相当于fgrep,不支持正则表达式
-f file 根据模式文件处理
NOTE:
egrep=grep -E 支持扩展正则表达式
fgrep=grep -F 不支持正则表达式
语法:
egrep [OPTIONS] PATTERN [FILE...]
fgrep [OPTIONS] PATTERN [FILE...]
练习
https://www.jianshu.com/p/42f04ee8a61c
4.2 sed
4.2.1 语法格式
sed [option]... 'script' inputfile...
script: ‘地址定界’
4.2.2 sed的工作模式
sed工作模式.jpgsed读取每个文件,一次读一行,将读取的行放到内存的模式空间;编辑命令修改模式空间中的内容;未编辑的内容可以暂时放到保持空间,而保持空间当中的内容又可以重新被读取到模式空间,随后可以继续编辑;当所有操作完成后,sed将模式空间的最后内容打印到标准输出。
4.2.3 常用选项
-n:不输出模式中的内容至屏幕,默认行为是将模式空间的内容输出到屏幕
-e script, --expression=script:多点编辑
多点编辑时,每个模式前都要加-e
-f /PATH/TO/SCRIPT_FILE: 从指定文件中读取编辑脚本
-r, --regexp -extend: 支持使用扩展正则表达式
-i [SUFFIX], --in-place [-SUFFIX]: 直接对原文件进行编辑
4.2.4 地址定界
1. 不给地址:对全文进行处理
2. 单地址:
#: 指定的行
/pattern/: 被此处模式所有能够匹配的每一行
3. 地址范围:
#,#
#,+#
/pat1/,/pat2/
#,/pat1/
4.~: 步进
1~2:表示1,3,5...所有奇数行
2~2:表示2,4,6...所有偶数行
4.2.5 编辑命令
d: 删除(d命令与之前sed处理模式行为不一致,先删除在匹配,此时不需要-n)
sed '1,5d' /etc/fstab
p: print the context pattern space 显示模式空间中的内容
sed '1~2p' /etc/fstab
sed -n '1~2p' /etc/fstab
a \text: 在行后面追加文本:支持\n实现多行追加
i \text: 在行前面插入文本:支持使用\n实现多行追加
c \text:替换行为单行或多行文本
sed '3i \new line' /etc/fstab 在第三行上面插入一行new line
sed '3a \new line' /etc/fstab 在第三行上面插入一行new line
sed '3a \new line \nanother newline' /etc/fstab 在第三行下面插入两行
sed '/^UUID/a\# add new device base on UUID' /etc/fstab
在UUID开头的行下面添加一行#add new device base on UUID
w /path/to/somefile:保存模式空间中的内容至指定文件中
sed -n '/^[^#]/p' /etc/fstab
显示非#开头的行
sed -n '/^[^#]/w /tmp/fstab.bak' /etc/fstab
把非#开头的行保存至/tmp/fstab.bak文件里
r /path/from/somefile:读取指定文件的文本流至当前文件模式匹配的行后面,实现文本合并
sed '3r /etc/issue' /etc/fstab
把issue文件写在fstab文件第3行的后面(文件合并)
sed '/^UUID/r /etc/issue' /etc/fstab
把issue文件写在fstab文件中以UUID开头的行后面
=: 为模式空间中的行打印行号
sed '/^UUID/=' /etc/fstab 把UUID开头的行上面加一行号
!: 取反条件,地址定界!编辑命令
sed '/^[^#]/d' /etc/fstab 删除非#开头的行
sed '/^#/!d' /etc/fstab 删除非#开头的行
! sed '/^#/d' /etc/fstab 删除非#开头的行
s///: 查找替换,支持使用其他分隔符,s@@@,s###
替换标记:
g: 行内全局替换
p: 显示替换成功的行
w /PATH/TO/SOMEFILE: 将替换成功的结果保存至指定文件中
4.2.6 高级编辑命令
h: 把模式空间中内容覆盖至保持空间中
H: 把模式空间中内容追加至保持空间中
g: 从保持空间取出数据覆盖至模式空间
G: 从保持空间取出内容追加至模式空间
x: 把模式空间中的内容与保持空间中的内容进行互换
n: 读取匹配到的行的下一行至模式空间
N: 追加匹配到的行的下一行至模式空间
d: 删除模式空间中的行
D: 删除多行模式空间中的所有行
4.3 awk
4.3.1 awk介绍
awk: Aho, Weinberger, Kernighan,报告生成器,格式化文本输出
有多种版本: New awk( nawk), GNU awk( gawk)
gawk:模式扫描和处理语言
基本用法:
awk [options] 'program' var=value file…
awk [options] -f programfile var=value file…
awk [options] 'BEGIN{action;… }pattern{action;… }END{action;… }' file ...
awk 程序可由: BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成
program 通常是被放在单引号中
选项:
-F “分隔符” 指明输入时用到的字段分隔符
-v var=value 变量赋值
基本格式: awk [options] 'program' file…
Program: pattern{action statements;..}
pattern和action
pattern部分决定动作语句何时触发及触发事件
BEGIN,END
action statements对数据进行处理,放在{}内指明
print, printf
分割符、域和记录
awk执行时, 由分隔符分隔的字段(域)标记$1,$2...$n称为域标识。 $0为所有域,注意:此时和shell中变量$符含义不同
文件的每一行称为记录
省略action,则默认执行 print $0 的操作
4.3.2 awk工作原理
第一步:执行BEGIN{action;… }语句块中的语句
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,
从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;…}语句块
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输
出表格的表头等语句通常可以写在BEGIN语句块中
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是
在END语句块中完成,它也是一个可选语句块
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认
执行{ print },即打印每一个读取到的行, awk读取的每一行都会执行该语句块
网友评论