本文介绍了如何使用linux正则表达式结合命令处理文本和awk,grep,sed三种文本工作命令。
正则表达式(regular expression)
使用一些特殊字符+字母和或数字按照某个规则组合成一 个公式用来表示某个意思这就叫正则表达式。正则表达式是一种方法,很多命令可以采用这种方法:vim ,grep,sed,awk等都支持正则表达式,grep通常打印结果行。
元字符
元字符:有特殊含义的字符,可以表示其他的含义
“ ^ “ 开头
匹配后面的某开头字符。
cat a.txt | grep "^a"
1 | a bc |
“ $ “ 结尾
匹配前面的某结尾字符。
cat a.txt | grep "b$"
1 | aa aab |
“ . “单个
匹配任意单个字符,长度不为0。
“a.{2}” 表示匹配以a开头的后面任意两个单个字符,至少两个,包括空格。
cat a.txt| egrep "a.{2}"
1 | a b |
“a.{4,6}” 表示匹配以a开头的后面任意4 - 6个单个字符,包括空格。
cat a.txt| egrep "a.{4,6}"
1 | bbb aaaaa |
“ * “ 任意
匹配前面的字符出现0次或者任意,贪婪模式, 匹配*号前面的字符任意次,.
*表示任意长度任意字符,包括空格。
cat a.txt| egrep "aa.*"
1 | aad da |
“ + “ 至少一次
表示前面字符出现1次以上.
cat a.txt | egrep "[abc]+"
1 | abcde |
相当于 cat a.txt| egrep "[abc]"
cat a.txt | egrep "abc+"
1 | abc |
“ ? “ 可有可无
匹配其前面的字符0或1次,即前面的字符可有可无。
cat a.txt| egrep "ab?"
1 | ab |
“{ }”次数区间
注意,在使用grep基本正则表达式要带\
转义字符,即\{4,6\}
,这里以拓展正则表达式为例,就不用带转义字符。
{m} ,匹配前面的字符m次。
{m,n} ,匹配前面字符至少m次,最多n次。
cat a.txt| egrep "abcd{2,3}"
1 | ef abcdd |
“ | “或者
cat a.txt| egrep "a|bc"
1 | bc as |
^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 | abd efg |
1 | ([0-9])|([0][0-9])|([1][0-9]) |
^在方括号里面和外面的区别
方括号里面:表示对字符取反,排除某些字符。
方括号外面:表示以某字符开头。
示例:查找不是以数字开头的行
行开头可能是字母或特殊字符。
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 | a 在当前行后添加一行或多行 |
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 | 7 14 74 a.txt |
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,统计重复行的出现次数