Hike News
Hike News

linux正则表达式与三剑客

本文介绍了如何使用linux正则表达式结合命令处理文本和awk,grep,sed三种文本工作命令。

正则表达式(regular expression)

使用一些特殊字符+字母和或数字按照某个规则组合成一 个公式用来表示某个意思这就叫正则表达式。正则表达式是一种方法,很多命令可以采用这种方法:vim ,grep,sed,awk等都支持正则表达式,grep通常打印结果行。

元字符

元字符:有特殊含义的字符,可以表示其他的含义

“ ^ “ 开头

匹配后面的某开头字符。

cat a.txt | grep "^a"

1
2
a bc
abc
“ $ “ 结尾

匹配前面的某结尾字符。

cat a.txt | grep "b$"

1
2
aa aab
bbb
“ . “单个

匹配任意单个字符,长度不为0。

“a.{2}” 表示匹配以a开头的后面任意两个单个字符,至少两个,包括空格。

cat a.txt| egrep "a.{2}"

1
2
3
a b
aaaa abc
bbb afc

“a.{4,6}” 表示匹配以a开头的后面任意4 - 6个单个字符,包括空格。

cat a.txt| egrep "a.{4,6}"

1
2
3
bbb aaaaa
abd efddd
kkk baccccd
“ * “ 任意

匹配前面的字符出现0次或者任意,贪婪模式, 匹配*号前面的字符任意次,. *表示任意长度任意字符,包括空格。

cat a.txt| egrep "aa.*"

1
2
aad da
ABC baa
“ + “ 至少一次

表示前面字符出现1次以上.

cat a.txt | egrep "[abc]+"

1
2
3
abcde
ade
bbb

相当于 cat a.txt| egrep "[abc]"

cat a.txt | egrep "abc+"

1
2
3
abc
abccc d
dd abc
“ ? “ 可有可无

匹配其前面的字符0或1次,即前面的字符可有可无。

cat a.txt| egrep "ab?"

1
2
3
ab
a
dd aad
“{ }”次数区间

注意,在使用grep基本正则表达式要带\转义字符,即\{4,6\},这里以拓展正则表达式为例,就不用带转义字符。

{m} ,匹配前面的字符m次。
{m,n} ,匹配前面字符至少m次,最多n次。

cat a.txt| egrep "abcd{2,3}"

1
2
ef abcdd
abcdddef
“ | “或者

cat a.txt| egrep "a|bc"

1
2
bc as
dd bcd
^patten$ 模式匹配

^a$表示只匹配以a这个字符开头和结尾的行。

cat a.txt | egrep "^a$"

“\“ 转义

“\“表示是转义字符,就是把元字符转义为普通字符,比如\\表示普通符号”\“,把普通字符转换为特殊意义符号,比如”\n”表示把普通字符n转义为换行符。

\<或\b    ,单词左侧,表示以该单词为词首
\>或\b    ,单词右侧,表示以该单词为词尾
\<PATTERN\> ,匹配整个单词

“[ ]”方括号表达式

[abc] 表示 a,b,c任意一个,实际上,[abc] = “a|b|c”=(a|b|c)。

示例:

[a-z] 表示小写字母

[A-Z] 表示大写字母

[0-Z] 表示数字和字母

egrep (ab|ba) a.txt

1
2
abd efg
acd baef
1
2
([0-9])|([0][0-9])|([1][0-9])
#表示匹配0-9或者00-09或者10-19范围的字符。
^在方括号里面和外面的区别

方括号里面:表示对字符取反,排除某些字符。

方括号外面:表示以某字符开头。

示例:查找不是以数字开头的行

行开头可能是字母或特殊字符。

cat a.txt| egrep "^[^0-9]"

[]和 {}组合使用

[0-9]{2} 表示0-9里面可以取2次的意思。

[0-9]{2,5} 表示从0-9里可以取2-5次的数字,至少2个数字,最多5个。

[0-9]{2,} 表示从0-9里可以取两次以上,最少2次

a{2} 表示花括号前面的a连续出现两次。

abc{2}表示abc中的c出现2次。

案例:从文本里面过滤出所有邮箱地址

root@localhost lianxi]# cat mail.txt
a a1@qq.com aa
b 2b@sina.com bb
c c3@163.com cc
d 4d@163.com dd

写一个表示邮箱的正则,过滤邮箱。邮箱地址:字符串1@字符串2.字符串3

字符串1:a-Z_0-9

字符串2:0-Z

字符串3:a-Z

cat mail.txt | grep -o "[0-Z$_]+@[0-z]+.[0-z]+"

awk

-F,字段分隔符,默认为空格

-f,从脚本中读取命令

1)以冒号为分割,显示第一列和第三列的内容:

awk -F :'{print $1 "\t" $3}' a.txt

2)以冒号为分割,显示UID大于500的用户信息:

awk -F : '$3>500' /etc/passwd

3)以冒号为分割,搜索含root关键字的所有行:

awk -F '/root/' /etc/passwd

4)以冒号为分割,搜索UID大于500的用户,并显示sh

awk -F : '$3>500{print $7}' /etc/passwd

5)BEGIN AND

awk -F : 'BEGIN{print "name \t uid"}{print $1 "\t" $3}END{print"from /etc/passwd"}' /etc/passwd

grep

用法: grep [选项] PATTERN [FILE]

在每个 FILE 或是标准输入中查找 PATTERN。默认的 PATTERN 是一个基本正则表达式(缩写为 BRE),也可以是拓展正则表达式。

例如: grep -i ‘hello world’ menu.h main.c

options:

-e : 使用正则表达式,用于指定多个搜索模式。

-E:使用拓展表达式

-i : ignore-case忽略大小写

-v: 反转匹配。

-w, –word-regexp ,强制 PATTERN 仅完全匹配字词。

-x:完全匹配整行内容,包括行首行尾空格内容都要完全匹配。

-f : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。

-c: 输出每个文件所匹配到的行数。

-r:递归搜索匹配内容

-L:列出不满足匹配要求的文件名,不输出行内容

-l : 列出满足匹配要求的文件名,不输出行内容。

-z :匹配一个 0 字节的数据行,但不是空行。

-m n:当匹配内容的行数达到n行后停止搜索,并输出停止前搜索到的匹配内容。

-o: 只输出匹配的具体字符串,匹配行中其他内容不会输出。

-q:安静模式,不会有任何输出内容,echo $?查找到匹配内容会返回0,未查找到匹配内容就返回非0

-s:不会输出查找过程中出现的任何错误消息。

输出线前缀控制:

-b:输出每一个匹配行或字符串时附上偏移量(从文件第一个字符到该匹配内容之间的字节数)

-n:输出匹配内容的同时输出其所在行号。

-H:在每一个匹配行之前加上文件名一起输出。

-h:不带文件名输出。

-T:在匹配信息和其前的附加信息之间加入tab以使格式整齐。

上下文线控制选项:

-A n:匹配到搜索到的行以及该行下面的n行

-B n:匹配到搜索到的行以及该行上面的n行

-C n:匹配到搜索到的行以及上下各n行

案例1:在/home目录下查找所有内容含abc的文件名

grep -rl abc *

案例2:统计在passwd和shadow文件中含root的行数

grep -c root /etc/passwd /etc/shadow

sed

sed 全名为 stream editor,流编辑器,用程序的方式来编辑文本,功能相当的强大。是贝尔实验室的 Lee E.M 在 1974年开发完成,目前可以在大多数操作系统中使用。与vim等编辑器不同,sed 是一种非交互式编辑器,它使用预先设定好的编辑指令对输入的文本进行编辑,完成之后再输出编辑结构。

sed会一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,成为”模式空间”pattern space,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾,文件内容并没有改变。

用法:sed [options] ‘command’ file,options有-n,-e,-i,-f,-r选项。

-n 使用安静模式,加入-n 后只打印被匹配的行。
-e 多重编辑,命令顺序会影响结果。
-r 使用扩展正则表达式。
-i 将操作结果写入文档,不在屏幕上输出。
-f 指定一个 sed 脚本文件到命令行执行。

COMMNAD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a        在当前行后添加一行或多行
c 用新文本修改(替换)当前行中的文本
d 删除行
i 在当前行之前插入文本
p 从暂存区打印行
s 用一个字符串替换另一个
h 把模式空间里的内容复制到暂存缓存区
H 把模式空间里的内容追加到暂存缓存区
g 取出暂存缓冲区里的内容,将其复制到模式空间,覆盖该处原有内容
G 取出暂存缓冲区里的内容,将其复制到模式空间,追加在原有内容后面
l 列出非打印字符
n 读入下一输入行,并从下一条命令而不是第一条命令开始处理
q 结束或退出 sed
r 从文件中读取输入行
! 对所选行之外的所有行应用命令

1)安静打印

sed -n 'p' a.txt

sed 'r' a.txt

2)每行打印两遍输出

sed 'p' a.txt

3)只输出第2到5行,原文件内容不变

sed -n '2,5p' a.txt

4)打印第4行后退出

sed '4q' a.txt

5)搜索指定内容并打印

找到含abc的行并把该行输出:

sed -n '/abc/p' a.txt

注意与sed '/abc/p' a.txt的区别,这是全部输出并把这行打印2遍。

6)删除

删除第2,到4行的数据:

sed '2,4d' a.txt

删除含abc的行:

sed '/abc/d' a.txt

7)追加a和插入i

在第二行下插入abc

sed '2a abc' a.txt

在第二行上插入abc

sed '2i abc' a.txt

8)整行替换

替换2,3,4行为abc

sed '2,4c abc' a.txt

9)字符串替换

全局替换将文件中的abc替换为a字符,g(global)

sed 's/abc/a/g' a.txt

仅换将文件中第3行的abc替换为a字符

sed '3s/abc/a/g' a.txt

多条件替换

将abc和def替换为a字符

sed -e 's/abc/a/g;s/def/a/g' a.txt

10)结果写入

使用-i选项,将原本输出到屏幕的结果写入文档。

sed -i '/abc/p' a.txt

11)从文件读入

子命令r,类似于a,也是将内容追加到指定行的后边,只不过r是将指定文件内容读取并追加到指定行下边。

例:sed '2r b.txt' a.txt

将b.txt文件内容读取并插入到a.txt文件第2行的下边。

其他文本处理命令

nl 编写行号

nl [options] [file],默认空行不统计

-b,选择样式,a所有、t非空行、n不显示、BRE正则(正则匹配的行才显示行号)

-n,–number-format=格式,根据指定格式插入行号。

-w, –number-width=数字,为行号使用指定的栏数。

-s, –number-separator=字符串,可能的话在行号后添加字符串。

格式是下列之一:

ln 左对齐,空格不用0 填充
rn 右对齐,空格不用0 填充
rz 右对齐,空格用0 填充

nl -b a a.txt,统计a.txt中所有行,

wc词数统计

wc [options] [file]

wc a.txt

1
2
3
4
5
6
7
8
9
7 14 74 a.txt
#行数 字(单词)数 字节数
$1 1111 aaa
$2 22222 bbb
$3 33333 cccc
$4 44444 ddd
$5 bbb aaaaa
$6 abd efddd
$7 kkk baccccd

options:

-w,只统计文件中单词数

-m,字符数

-c,统计字节数

-L,显示最长行长度(可见字符加空格)

-l,行数

sort

sort a.txt,文本排序,默认按首字母、第一个数字顺序排序。

options:

-n,按数值大小排序。

-r,逆序排列。

-t,指定分隔符

-k,选取分隔后的哪一列

案例:按a.txt文件中第三列数字大小进行排序输出

sort -k 3 -n a.txt

uniq

uniq a.txt,去连续重行。

-d,只打印重复的行

-u,只打印不重复的行

-c,统计重复行的出现次数