摘要:概述、语系的影响、grep进阶、正则表达式字符、sed工具、awk工具、文件编排
一、概述
【什么是正则表达式】
正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去匹配符合规则的字符。
【使用正则表达式的条件】
必须要使用可以支持正则表达式的工具程序,譬如vi、grep、awk、sed等工具。
【正则表达式的广泛用途】
在信息海里选取重要信息、过滤广告信件、应用于很多服务器软件。
【基础/扩展正则表达式】
区分:正则表达式的字符串表示方式依据不同的严谨度而分为基础正则表达式与扩展正则表达式。
即,不同的特殊字符的性质带来了正则表达式的细分。
二、语系对正则表达式的影响
1. 编码概述
文件记录的字符文字与数字其实都是0/1序列经过编码表转换来的。
由于不同语系的编码数据并不相同,所以就会造成数据选取结果的区别。下面以两种语系zh_CN.big5和C来解释。
- LANG=C时:0 1 2 3 4 ... A B C D ... Z a b c d ... z
- LANG=zh_CN时:0 1 2 3 4 ... a A b B c C d D ... z Z
可以看出,在这两种不同的语系下,编码的顺序也并不一致。
如果我们要选取大写字符而使用[A-Z]时,会发现LANG=C确实可以仅找到大写字符(因为是连续的),但是如果使用LANG=zh_CN.gb2312时,就会发现连小写的b-z也会被选取出来。所以,当使用正则表达式时,需要留意当时环境的语系为何,否则可能会发现结果事与愿违。
2. 避免语系影响的特殊符号
虽然我们在练习正则表达式的时候,会事先设置好语系(LANG=C),但百密一疏的事总会发生,所以我们可以使用以下的特殊符号替代可能出错的字符选取。
声明:下面的特殊符号在任何语系下的意思都是一致的!
特殊符号 | 代表意义 |
[:alnum:] | 0-9,A-Z,a-z |
[:digit:] | 0-9 |
[:alpha:] | A-Z,a-z |
[:upper:] | A-Z |
[:lower:] | a-z |
三、grep的一些高级参数
传送门:grep的基本用法
1. 重点重申
grep最重要的功能:进行字符串数据的对比,然后将符合用户需求的字符串打印出来。
注:grep在数据中查找一个字符串时,是以整行为单位来进行数据的选取的!
2. 进阶用法
grep [-A] [-B] '搜寻字符串' filename //-A(B)后可加数字,为after(before)的意思,除了列出该行外,后续(前面)的n行也列出来
3. 示例
题目1:用dmesg列出内核信息,再以grep找出内含eth的那行
命令:dmesg | grep 'eth'
题目2:承上,要将找到的关键字显色,且加上行号来表示
命令:dmesg | grep -n --color=auto 'eth'
题目3:承上,在关键字所在行的前两行与后三行也一起找出来显示
命令:dmesg | grep -n -A3 -B2 --color=auto 'eth'
四、基础正则表达式字符
RE字符 | 意义 |
^word | 待查找的字符串(word)在行首 |
word$ | 待查找的字符串(word)在行尾 |
. | 一定有一个任意字符的字符 |
转移字符,将特殊符号的特殊意义去除 | |
* | 重复0个到无穷多个前一个字符 |
[list] | 从字符集合的RE字符里面找出想要选取的字符 |
[n1-n2] | 从字符集合的RE字符里面找出想要选取的字符范围 |
[^list] | 从字符集合的RE字符里面找出不要的字符串或范围 |
{n,m} | 连续n到m个的前一个RE字符,若为{n}则是连续n个前一个RE字符,若为{n,}则是连续n个以上的前一个RE字符 |
【重要搭配】
.*:代表0个或多个任意字符
五、基础正则表达式练习
【预处理】
语系:LANG=C
待处理的文件名:zzs.txt
1. 查找特定字符串
题目:从文件中取得the这个特定字符串
命令:grep 'the' zzs.txt
2. 利用中括号[]来查找集合字符
题目:查找test或taste这两个单词
命令:grep 't[ae]st' zzs.txt
评讲:其实[]里面无论有几个字符,它都只代表某“一个”字符。即我需要的字符串时“tast”或“test”两个字符串而已。
题目:查找到有oo的字符
命令:grep 'oo' zzs.txt
题目:oo前面不要有g
命令:grep '[^g]oo' zzs.txt
题目:oo前面不要有小写字符
命令:grep '[^a-z]oo' zzs.txt or grep '[^[:lower:]]oo' zzs.txt
题目:取得有数字的那一行
命令:grep '[0-9]' zzs.txt or grep '[[:digit:]]' zzs.txt
3. 行首与行尾字符^$
题目:the只在行首列出
命令:grep '^the' zzs.txt
题目:开头是小写字符的那一行就列出
命令:grep '^[a-z]' zzs.txt or grep '^[[:lower:]]' zzs.txt
题目:不想要开头是英文字母
命令:grep '^[^a-zA-Z]' zzs.txt or grep '^[^[:alpha:]]' zzs.txt
评讲:^在[]内代表“反向选择”,在[]外代表定位在行首
题目:找出行尾结束为小数点(.)的那一行
命令:grep '.$' zzs.txt
评讲:小数点具有特殊意义,故需转义
题目:找出所有空白行
命令:grep '^$' zzs.txt
题目:剔除空白行和以#开头的行
命令:grep -v '^$' zzs.txt | grep -v '^#'
4. 任意一个字符.与重复字符*
题目:找出g??d的字符串
命令:grep 'g..d' zzs.txt
评讲:强调g与d之间一定要存在两个字符,故gd、god等就不会显示
题目:列出有oo, ooo, oooo等的数据(即至少包含两个o)
命令:grep 'ooo*' zzs.txt
评讲:“0*”代表的是具有空字符或一个o以上的字符
题目:要字符串开头与结尾都是g,但两个g之间仅能存在至少一个o
命令:grep 'goo*g' zzs.txt
题目:找出g开头与g结尾的字符串,当中的字符可有可无
命令:grep 'g.*g' zzs.txt
评讲:“.*”代表的是0个或多个任意字符
题目:取得有数字的那一行
命令:grep '[0-9]' zzs.txt or grep '[[:digit:]]' zzs.txt or grep '[0-9][0-9]*' zzs.txt
5. 限定连续RE字符范围{}
题目:取得两个o的字符串
命令:grep 'o{2}' zzs.txt or grep 'ooo*' zzs.txt
评讲:“{”和“}”都是特殊符号,故需转义
题目:找出g后面接2到5个o,然后再接一个g的字符串
命令:grep 'go{2,5}g' zzs.txt
题目:找出g后面接至少2个o以上,然后再接一个g的字符串
命令:grep 'go{2,}g' zzs.txt or grep 'gooo*g' zzs.txt
六、扩展正则表达式字符
RE字符 | 意义及范例 |
+ |
重复一个或一个以上的前一个RE字符 如:egrep 'go+d' zzs.txt |
? |
零个或一个前一个RE字符 如:egrep 'go?d' zzs.txt |
| |
用或(or)的方式找出数个字符串 如:egrep 'gd|good' zzs.txt |
() |
找出“组”字符串 如:egrep 'g(la|oo)d' zzs.txt |
()+ |
多个重复组的判别 如:echo 'AxyzxyzxyzxyzC' | egrep 'A(xyz) +C' |
七、sed工具
1. sed概述
sed是一个管道命令,可以分析stdin
sed的功能:替换/删除/新增/选取特定行
2. 命令
sed [-n] [动作] //-n会将只有经过sed特殊处理的那一行(或操作)列出来,因为sed默认会将所有来自stdin的数据都列出来
动作说明:[n1[,n2]] function
n1, n2:不一定会有,一般代表选择进行动作的行数
function有下面这些参数:a/c/d/i/p/s
a:新增,后面接字符串,这些字符串会在目前行的下一行出现
c:替换,后面接字符串,这些字符串可以替换n1,n2之间的行
d:删除,后不接任何参数
i:插入,后面接字符串,这些字符串会在目前行的上一行出现
p:打印,将某个选择的数据打印出来,通常会与参数sed -n一起运行
s:替换,直接进行替换,可以搭配正则表达式
3. 以行为单位的新增/删除功能
题目:将/etc/passwd的内容列出并打印行号,同时,将第2~5行删除
命令:nl /etc/passwd | sed '2,5d'
题目:将/etc/passwd的内容列出并打印行号,同时,将第2行删除
命令:nl /etc/passwd | sed '2d'
题目:将/etc/passwd的内容列出并打印行号,同时,将第2到最后一行删除
命令:nl /etc/passwd | sed '2,$d'
题目:承上例,在第二行后加上“drink tea?”字样
命令:nl /etc/passwd | sed '2a drink tea?'
题目:承上例,在第二行前加上“drink beer?”字样
命令:nl /etc/passwd | sed '2i drink beer?'
4. 以行为单位的替换与显示功能
题目:将第2~5行的内容替换为“No 2-5 number”
命令:nl /etc/passwd | sed '2,5c No 2-5 number'
题目:仅列出/etc/passwd文件内的第5-7行
命令:nl /etc/passwd | sed -n '5,7p' or nl /etc/passwd | head -n 20 | tail -n 10
评讲:如果去掉-n会差很多的!
5. 部分数据的查找并替换
上面的都是整行的处理模式,sed还可以用行为单位进行部分数据的查找并替换。
sed的查找和替换与vi相当类似,形式为:sed 's/要被替换的字符串/新的字符串/g'
题目:如有这么一段:inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0,我们要取出其中的IP地址段(即标红的区域),该怎么办?
命令1:sed 's/^.*addr://g' //删除IP前面的部分
命令2:sed 's/Bcast.*$//g' //删除IP后面的部分
6. 与正则表达式的配合
题目:在/etc/man.config中,我不要带#的批注和空白行,只要存在MAN字样的那几行数据
命令:cat /etc/man.config | grep 'MAN' | sed 's/#.*$//g' | sed '/^$/d'
7. 直接修改文件内容(危险)
题目:将每一行结尾为“.”的换成“!”
命令:sed -i 's/.$/!/g' zzs.txt
评讲:-i可以让sed直接去修改后面接的文件内容而不是由屏幕输出
题目:利用sed直接在文件的最后一行加入“# This is a test”
命令:sed -i '$a # This is a test' zzs.txt
八、格式化打印
1. 命令
print '打印格式' 实际内容
参数:a f v xNN
a:警告声音输出
:退格键
f:清除屏幕
:输出新的一行
:以及Enter按键
:水平的Tab按键 //最常用来分隔数据的符号,因为它可以将数据做个整齐的排列
v:垂直的Tab按键
xNN:NN为两位数的数字,可以转换数字成为字符
关于C语言内,常见的变量格式为:%ns %ni %N.nf
%ns:n是数字,s代表string,即多少个字符
%ni:n是数字,i代表integer,即多少整数字数
%N.nf:N和n都是数字,f打表floating,如果有小数,假设我共有十个位数,但小数为有两位,即%10.2f
2. 用法示例
- printf '%s %s %s %s %s ' $(cat zzs.txt)
- printf '%10s %5i %5i %5i %8.2f ' $(cat zzs.txt | grep -v 'Name')
九、awk工具
1. 概述
awk是一个数据处理工具。
相比于sed常常作用于一整行的处理,awk则比较倾向于将一行分成数个“字段”来处理。
故awk最常用的动作就是将字段数据列出来。
2. 用法
awk '条件类型1{动作1} 条件类型2{动作2} ... ' filename
//awk可以处理后续接的文件,也可以读取来自前个命令的stdout