linux文本处理三剑客之grep文本处理工具
grep,egrep fgrep: 文本过滤工具(模式:pattern)工具;
grep: 基本正则表达式,—E,-F
egrep: 扩展正则表达式,-G,-F
fgrep: 不支持正则表达式(搜索速度快得快得多); -F
sed: stream editor,流编辑器;文本编辑工具
awk: linux上的实现为gawk,文本报告生成器(格式化文本);
正则表达式: Regual Expression REGEXP
由一类特殊字符及文本字符编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配功能;
分两类:
基本正则表达式:BRE
扩展正则表达式:ERE
元字符:\(hello[[:space:]]\+\)\+
grep: Global search Regular Expression and Print out the line.
作用:文本搜索工具,根据用户指定的"模式"(过渡条件)对目标文本逐行进行匹配检查;打印匹配到的行;
模式:由正则表达式的元字符及文本字符所编写的过渡条件
正则表达式引擎:
grep及grep参数介绍
grep [OPTIONS] PATTERN [FILE...]
man grep
基本正则表达式元字符分4类:字符匹配:
. 匹配任意单个字符 #grep 'r..t' /etc/passwd
[] 匹配指定范围内的任意单个字符
[^] 匹配指定范围外的任意单个字符
表示字符匹配范围:
[:digit:] 表示匹配单个所有的数字
[:lower:] 表示匹配单个所有小写字符
[:upper:] 表示匹配单个所有大写字符
[:alpha:] 表示匹配单个所有字母
[:alnum:] 包含单个数字和字母
[:punct:] 单个所有标点符号
[:space:] 单个空白字符
例如:匹配r-t之间出现2个字符:
grep "r[[:alpha:]][[:alpha:]]t" /etc/passwd
#如果匹配r-t之间出现10个字符?:
匹配次数:
用在要指定其出现的次数的字符的后面,用于限制其前面字符出现的次数;默认工作于贪婪模式;
* 匹配其前面的字符任意次:0,1,多次;
例如: grep "x*y"
abxy
aby
xxxxxxxy
yab
.* 匹配任意长度的任意字符
grep --color=auto 'r.*' /etc/passwd
\? 匹配其前面的字符0次或1次;即前面的字符是可有可无的;
[root@linux-node11 scripts]# nano grep.txt
abxy
aby
xxxxxxxy
yab
[root@linux-node11 scripts]# grep "x*y" grep.txt
abxy
aby
xxxxxxxy
yab
[root@linux-node11 scripts]# grep "x\?y" grep.txt
abxy
aby
xxxxxxxy
yab
\+ 匹配其前面的字符1次或多次,即其前面的字符要出现至少1次;
[root@linux-node11 scripts]# grep "x\+y" grep.txt
abxy
xxxxxxxy
\{m\} 匹配其前面的字符m次;
[root@linux-node11 scripts]# grep "x\{1\}y" grep.txt
abxy
xxxxxxxy
注意:匹配时候加上--color=auto可以看清楚字符;
\{m,n\} 匹配其前面的字符至少m次,至多n次;
[root@linux-node11 scripts]# grep --color=auto "x\{2,5\}y" grep.txt
xxxxxxxy
\{0,n\} 匹配至多n次;
\{m,\} 匹配至少m次;
位置锚定:
[root@linux-node11 scripts]# useradd rootkit
[root@linux-node11 scripts]# useradd -s /bin/chroot user4
[root@linux-node11 scripts]# useradd chrooter
^ 行首锚定;用于模式的最左侧;
$ 行尾锚定;用于模式的最右侧;
[root@linux-node11 scripts]# grep "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
rootkit:x:500:500::/home/rootkit:/bin/bash
[root@linux-node11 scripts]# grep "root$" /etc/passwd
user4:x:501:501::/home/user4:/bin/chroot
^PATTERN$ 用于PATTERN来匹配整行;
^$ 配置空白行;
^[[:space:]]*$ 空行或包含空白字符的行;
单词:非特殊字符组成连续(字符串)都称为单词;
\<或\b 词首锚定,用于单词模式的左侧;
[root@linux-node11 scripts]# grep --color=auto "\<root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rootkit:x:500:500::/home/rootkit:/bin/bash
\>或\b 词尾锚定,用于单词模式的右侧;
[root@linux-node11 scripts]# grep --color=auto "root\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
user4:x:501:501::/home/user4:/bin/chroot
\<PATTERN\> 精确锚定单词也就是匹配完整单词;
[root@linux-node11 scripts]# grep --color=auto "\<root\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
练习:
1、显示/etc/passwd文件中不以/bin/bash结尾的行;
grep -v "/bin/bash$" /etc/passwd
2、找出/etc/passwd文件中两位数或三位数;
grep --color=auto "\<[0-9]\{2,3\}\>" /etc/passwd
3、找出/etc/rc.d/rc.sysinit或/etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行;
grep --color=auto "^[[:space:]]\+[^[:space:]]" /etc/rc.d/rc.sysinit
4、找出"netstat -tan"命令的结果中以"LISTEN"后跟0、1或多个空白字符结尾的行;
netstat -tan | grep "LISTEN[[:space:]]*$"
分组及引用正则表达式之分组与引用
\(\) 将一个或多个字符捆绑在一起,当作一个整体进行处理;这种就叫做分组匹配;
xy*ab: 表示y可以出现0次,1次或多次;
\(xy\)*ab: 表示xy可以出现0次,1次或多次,这种就叫做分组匹配;#因为在bash shell的括号有特殊意义所以要\转义;
Note: 分组括号中的模式匹配到的内容会被正则表达式引擎自动记录于内部的变量中,这些变量为:
\1: 模式从左侧起,第一个左括号以及与之匹配的右括号之间的模式所匹配到的字符;也就是后向引用;
\2 模式从左侧起,第二个左括号以及与之匹配的右括号之间的模式所匹配到的字符;也就是后向引用;
\3 模式从左侧起,第三个左括号以及与之匹配的右括号之间的模式所匹配到的字符;也就是后向引用;
……
He loves his lover.
He likes his lover.
She likes her liker.
She loves her like.
[root@linux-node11 scripts]# nano lovers.txt
He loves his lover.
He likes his lover.
She likes her liker.
She loves her like.[root@linux-node11 scripts]# grep --color=auto "l..e.*l..e" lovers.txt
He loves his lover.
He likes his lover.
She likes her liker.
She loves her like.[root@linux-node11 scripts]# grep --color=auto "\(l..e\).*\1" lovers.txt #后向引用
He loves his lover.
She likes her liker.
#匹配行首的root跟行中的root
[root@linux-node11 scripts]# grep "^\(r..t\).*\1" /etc/passwd
root:x:0:0:root:/root:/bin/bash
rootkit:x:500:500::/home/rootkit:/bin/bash
#后向引用:引用前面的分组括号中的模式所匹配到的字符;
#好了,基本正则表达式4类已讲完,接下来讲扩展正则表达式;
egrep介绍及egrep的元字符介绍:
egrep:
支持扩展的正则表达式实现类似于grep文本过滤功能;grep -E
man egrep
grep [OPTIONS] PATTERN [FILE...]
选项:
-i,-o,-v,-q,-A,-B,-C
-G:支持基本正则表达式
扩展正则表达式的元字符:
字符匹配:
. 任意单个字符
[] 指定范围内的任意单个字符;
[^] 指定范围外的任意单个字符
次数匹配:
* 任意次,0,1或多次;
? 0次或1次,其前面的字符可有可无的; #你看扩展正则表达式把转义符号去掉了;
+ 其前字符至少1次;
{m} 其前的字符m次;
{m,n} 至少m次,至多n次;
{0,n} 至多n次;
{m,} 至少m次;
位置锚定:
^ 行首锚定;
$ 行尾锚定;
\<或\b 词首锚定;
\>或\b 词尾锚定;
分组及引用:
() 分组;括号内的模式匹配到的字符会被记录于正则表达式引擎的内部变量中;
后向引用:\1,\2……; #你有几组括号,自动赋值到几组内置变量中,我们只能在正则表达式引用这些变量的值,不能在bash shell中引用;
或:
a|b a或者b;
C|cat C或者cat
(c|C)at cat或者Cat
接下来使用扩展正则在把练习做下:
1、显示/etc/passwd文件中不以/bin/bash结尾的行;
grep -v "/bin/bash$" /etc/passwd
2、找出/etc/passwd文件中两位数或三位数;
grep -E --color=auto "\<[0-9]{2,3}\>" /etc/passwd
3、找出/etc/rc.d/rc.sysinit或/etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行;
grep --color=auto "^[[:space:]]\+[^[:space:]]" /etc/rc.d/rc.sysinit
egrep --color=auto "^[[:space:]]+[^[:space:]]" /etc/rc.d/rc.sysinit
4、找出"netstat -tan"命令的结果中以"LISTEN"后跟0、1或多个空白字符结尾的行;
netstat -tan | grep "LISTEN[[:space:]]*$"
练习:
1、找出/proc/meminfo文件中,所有以大写或小写S开头的行;至少有三种实现方式;
grep "^[sS]" /proc/meminfo
grep -i "^s" /proc/meminfo
grep -E "^(s|S)" /proc/meminfo
2、显示当前系统上root、centos或user1用户的相关信息;
grep -E "^(root|centos|user1)\>" /etc/passwd
3、找出/etc/rc.d/init.d/functions文件中某单词后面跟一个小括号和行;
grep -E -o "[[:alnum:]]+\(\)" /etc/rc.d/init.d/functions
4、使用echo命令输出一绝对路径,使用egrep取出基名;
~]# echo /etc/sysconfig |egrep -o "[^/]+/?$"
sysconfig
进一步:取出路径名;类似于对其执行dirname命令的结果;
5、找出ifconfig命令结果中的1-255之间的数值;
ifconfig |egrep --color=auto -o "\<[1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]\>"
6、找出ifconfig命令结果中的IP地址;
~]# ifconfig eth0|grep "inet addr"|cut -d ":" -f2|cut -d " " -f1
10.211.55.11~]# ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
10.211.55.11
~]# ifconfig eth0|sed -rn 's#^.*dr:*(.*) Bc.*$#\1#gp'
10.211.55.11
7、添加用户bash,testbash,basher以及nologin(其shell为/sbin/nologin);而后找出/etc/passwd文件中用户名同shell名的行;~]# useradd bash
~]# useradd basher
~]# useradd testbash
~]# useradd -s /sbin/nologin nologin
先:~]# grep -E --color=auto "^[^:]+\>" /etc/passwd
~]# grep -E --color=auto "^([^:]+\>).*\1$" /etc/passwd
>大家实在看不懂那就背会,你说哪个牛人不是从小白成长起来的呢,谁的新欢不是别人的旧爱呢!
fgrep:不支持正则表达式元字符;
当无需要用到元字符去编写模式时,使用fgrep性能更好;
文本处理工具之wc、cut、sort介绍
文本查看及处理工具:wc,cut,sort,uniq,diff,patch
wc: word count
-l: lines
-w: words
-c: bytes
~]# wc /etc/fstab
11 54 465 /etc/fstab
行 单词数 字节数
~]# wc -l /etc/fstab
11 /etc/fstab
~]# wc -w /etc/fstab
54 /etc/fstab
~]# wc -c /etc/fstab465 /etc/fstab
cut:
OPTION:
-d CHAR: 以指定的字符为分隔符;
-f FILEDS:挑选出的字段
#: 指定的单个字段;
#-#: 连续的多个字段;
#,#: 离散的多个字段;
~]# cut -d ":" -f1,7 /etc/passwd
~]# cut -d: -f1,3-5,7 /etc/passwd
~]# wc -l /etc/rc.d/init.d/functions |cut -d" " -f1
605
sort:
OPTIONS:
-n: 基于数值大小排序而非字符进行排序;
-t CHAR: 指定分隔符;
-k #:用于排序比较的字段;
-r 逆序排序;
-f 忽略字符大小写;
-u 重复的行只保留一份;(重复行:表示连续且相同)
~]# sort /etc/passwd
~]# cut -d: -f3 /etc/passwd
~]# cut -d: -f3 /etc/passwd|sort -n
以第三字段进行排序:
~]# sort -t: -k3 -n /etc/passwd
~]# sort -t: -k3 -rn /etc/passwd
文本处理工具之uniq、diff、patch介绍
~]# cut -d: -f7 /etc/passwd|sort
~]# cut -d: -f7 /etc/passwd|sort -u
/bin/bash
/bin/sync
/sbin/halt
/sbin/nologin
/sbin/shutdown
~]# cut -d: -f7 /etc/passwd|sort -u|wc -l
5
统计shell有多少人使用:
~]# grep "bash$" /etc/passwd|wc -l
uniq: 报告或移除重复的行;
-c:显示每行的重复次数;
-u: 仅显示未曾重复的行;
-d: 仅显示重复的行;
uniq - report or omit repeated lines
~]# cut -d : -f7 /etc/passwd|sort|uniq -c
1 /bin/bash
1 /bin/sync
1 /sbin/halt
22 /sbin/nologin
1 /sbin/shutdown
不显示重复的行
~]# cut -d : -f7 /etc/passwd|sort|uniq -u
diff:
-u: 使用unfied机制,即显示雪修改的行的上下文,默认为3行;
~]# cp /etc/fstab ./fstab
~]# cp fstab fstab.new
~]# nano fstab.new
# commet #增加
~]# diff fstab fstab.new
2c2
< #
---
> # commet
~]# diff fstab fstab.new >fstab.patch
现在我们打补丁:
patch: 向文件打补丁
patch [OPTIONS] -i /PATH/TO/PATCH_FILE/PATH/TO/OLDFILE
patch /PATCH/TO/OLDFILE </PATH/TO/PATCH_FILE
~]# patch -i fstab.patch fstab
patching file fstab #已经打好补丁了
#接下来我们看下老文件:
~]# head -3 fstab
# commet #有了
# /etc/fstab
~]# diff fstab fstab.new
那么如果打好补丁后悔了呢?
还原回去:
~]# patch -R -i fstab.patch fstab
patching file fstab
[root@localhost ~]# head -3 fstab
# #还原了
# /etc/fstab
~]# diff -u fstab fstab.new
--- fstab 2017-08-23 22:24:45.946000000 +0800
+++ fstab.new 2017-08-23 22:13:59.103000000 +0800
@@ -1,5 +1,5 @@
-#
+# commet
# /etc/fstab
# Created by anaconda on Sat Feb 25 11:54:55 2017
#