linux命令三剑客(grep、sed、awk),日常开发中离不开的几大命令,尤其是几个命令结合使用时其功能更强大,可以大大提升服务器操作效率。
grep
grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
Unix的grep家族包括grep、egrep和fgrep。egrep和fgrep的命令只跟grep有很小不同。egrep是grep的扩展,支持更多的re元字符, fgrep就是fixed grep或fast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示回其自身的字面意义,不再特殊。linux使用GNU版本的grep。它功能更强,可以通过-G、-E、-F命令行选项来使用egrep和fgrep的功能。
grep基本使用
grep [-acinv] [--color=auto] '搜寻字符串' filename
选项与参数:
-a :将 binary 文件以 text 文件的方式搜寻数据
-c :计算找到 ‘搜寻字符串’ 的次数
-i :忽略大小写的不同,所以大小写视为相同
-n :顺便输出行号
-v :反向选择,亦即显示出没有’搜寻字符串’内容的那一行
–color=auto :可以将找到的关键词部分加上颜色的显示
从/etc/passwd,将有出现root
的行取出来
# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
或
# cat /etc/passwd | grep root
root:x:0:0:root:/root:/bin/bash
从/etc/passwd,将有出现 root 的行取出来,同时显示这些行在/etc/passwd的行号
# grep -n root /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
在关键字的显示方面,grep 可以使用 --color=auto 来将关键字部分使用颜色显示。但是如果每次使用 grep都得要自行加上–color=auto 又显的很麻烦,此时可以用alias
来处理一下,可以在 ~/.bashrc 内加上:alias grep='grep --color=auto'
再以source ~/.bashrc
来立即生效即可。这样每次运行grep
命令他都会自动帮我们加上颜色显示。
从/etc/passwd,将没有出现root
的行取出来
# grep -v root /etc/passwd
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
从/etc/passwd,将没有出现root
和nologin
的行取出来
# grep -v root /etc/passwd | grep -v nologin
sync:x:4:65534:sync:/bin:/bin/sync
用 dmesg 列出核心信息,再以 grep 找出内含 eth 那行,要将捉到的关键字显色,且加上行号来表示:
# dmesg | grep -n --color=auto 'eth'
1133:[ 12.629105] igb 0000:04:00.0: added PHC on eth0
1135:[ 12.629110] igb 0000:04:00.0: eth0: (PCIe:5.0Gb/s:Width x4) 00:25:90:c2:46:18
1136:[ 12.629183] igb 0000:04:00.0: eth0: PBA No: 106100-000
1148:[ 12.681007] igb 0000:04:00.1: added PHC on eth1
1150:[ 12.681012] igb 0000:04:00.1: eth1: (PCIe:5.0Gb/s:Width x4) 00:25:90:c2:46:19
1151:[ 12.681085] igb 0000:04:00.1: eth1: PBA No: 106100-000
用 dmesg 列出核心信息,再以 grep 找出内含 eth 那行,在关键字所在行的前两行与后三行也一起捉出来显示
# dmesg | grep -n -A3 -B2 --color=auto 'eth'
1131-[ 12.591633] nouveau 0000:06:00.0: NVIDIA GK208B (b060b0b1)
1132-[ 12.591676] nouveau 0000:06:00.0: irq 53 for MSI/MSI-X
1133:[ 12.629105] igb 0000:04:00.0: added PHC on eth0
1134-[ 12.629108] igb 0000:04:00.0: Intel(R) Gigabit Ethernet Network Connection
1135:[ 12.629110] igb 0000:04:00.0: eth0: (PCIe:5.0Gb/s:Width x4) 00:25:90:c2:46:18
1136:[ 12.629183] igb 0000:04:00.0: eth0: PBA No: 106100-000
1137-[ 12.629185] igb 0000:04:00.0: Using MSI-X interrupts. 8 rx queue(s), 8 tx queue(s)
1138-[ 12.629454] igb 0000:04:00.1: irq 55 for MSI/MSI-X
1139-[ 12.629487] igb 0000:04:00.1: irq 55 for MSI/MSI-X
--
1146-[ 12.629543] igb 0000:04:00.1: irq 62 for MSI/MSI-X
1147-[ 12.629551] igb 0000:04:00.1: irq 63 for MSI/MSI-X
1148:[ 12.681007] igb 0000:04:00.1: added PHC on eth1
1149-[ 12.681010] igb 0000:04:00.1: Intel(R) Gigabit Ethernet Network Connection
1150:[ 12.681012] igb 0000:04:00.1: eth1: (PCIe:5.0Gb/s:Width x4) 00:25:90:c2:46:19
1151:[ 12.681085] igb 0000:04:00.1: eth1: PBA No: 106100-000
1152-[ 12.681086] igb 0000:04:00.1: Using MSI-X interrupts. 8 rx queue(s), 8 tx queue(s)
1153-[ 12.703425] nouveau 0000:06:00.0: bios: version 80.28.a6.00.48
1154-[ 12.703901] nouveau 0000:06:00.0: priv: HUB0: 085014 ffffffff (1e70820b)
根据文件内容递归查找目录
# grep 'mysql' * #在当前目录搜索带'mysql'行的文件
# grep -r 'mysql' * #在当前目录及其子目录下搜索'mysql'行的文件
# grep -l -r 'mysql' * #在当前目录及其子目录下搜索'mysql'行的文件,但是不显示匹配的行,只显示匹配的文件
这几个命令很有用,是查找文件的利器
grep与正规表达式
字符的搜索: 如果想要搜寻test
或taste
这两个单词,可以发现到,其实她们有共通的 ‘t?st’ 存在,这个时候,我可以这样来搜索
# grep -n 't[ae]st' regular_express.txt
8:I can't finish the test.
9:Oh! The soup taste good.
[] 里面不论有几个字符,他都仅代表某一个字符,所以,上面的例子说明需要搜索的是tast
或test
两个字符串。
字符的反向选择[^]
,如果想要搜索到有oo
的行,但不想要oo
前面有g
,如下:
# grep -n '[^g]oo' regular_express.txt
2:apple is my favorite food.
3:Football game is not use feet only.
18:google is the best tools for search keyword.
19:goooooogle yes!
第2,3行没有疑问,因为foo
与Foo
均是符合要求的结果,但是第18行明显有google
的goo
,因为该行后面出现了tool
的too
所以该行也被列出来;第19行,同样的因为goooooogle
里面的oo
前面可能是o
,所以这一行也是符合要求。
连续字符的搜索:搜索oo
前面不要有小写字母
# grep -n '[^a-z]oo' regular_express.txt
3:Football game is not use feet only.
如果该字符组是连续的,例如大写英文/小写英文/数字等等, 就可以使用[a-z],[A-Z],[0-9]等方式来书写,例如果我们的要求字串是数字与英文,变成:[a-zA-Z0-9]。
获取有数字的那一行:
# grep -n '[0-9]' regular_express.txt
5:However, this dress is about $ 3183 dollars.
15:You are the best is mean you are the no. 1.
行首与行尾字符:^ $
查找the
开头的行:
# grep -n '^the' regular_express.txt
12:the symbol '*' is represented as start.
查找开头是小写字符的行:
# grep -n '^[a-z]' regular_express.txt
查找开头不是英文字母的行:
# grep -n '^[^a-zA-Z]' regular_express.txt
注意: ** ^
符号,在字符类符号(括号[])之内与之外是不同的,在[]
内代表反向选择
,在[]
之外代表定位在行首**
查找小数点.
结尾的行:
# grep -n '\.$' regular_express.txt
特别注意:因为小数点在正则表达式中具有其他意义(见后文),所以必须要使用转义字符\
。
查找空白行:
# grep -n '^$' regular_express.txt
因为只有行首跟行尾^$
,所以这样可以找出空白行.
任意一个字符.
与重复字符*
这两个符号在正则表达式的意义如下:
.
(小数点):代表一定有一个任意字符
*
(星号):代表重复前一个字符0到无穷多次
找出g??d
的字串,即共有四个字符,起头是g
而结束是d
,我可以这样做:
# grep -n 'g..d' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
9:Oh! The soup taste good.
16:The world <Happy> is the same with "glad".
因为强调g
与d
之间一定要存在两个字符,因此第13行的god
与第14行的gd
就不会被列出来.
如果想要列出有oo
,ooo
,oooo
等等的数据, 也就是说,至少要有两个(含)o
以上
因为*
代表的是重复0个或多个前面的RE字符
的意义, 因此o*
代表的是:拥有空字符或一个o
以上的字符
因此grep -n 'o*' regular_express.txt
将会把所有的数据都打印出来
当我们需要至少两个o
以上的字串时,就需要ooo*
,即:
# grep -n 'ooo*' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
2:apple is my favorite food.
3:Football game is not use feet only.
9:Oh! The soup taste good.
18:google is the best tools for search keyword.
19:goooooogle yes!
如果想要查找字符串开头与结尾都是g
,但是两个g
之间仅能存在至少一个o
,即gog
,goog
,gooog
等等:
# grep -n 'goo*g' regular_express.txt
18:google is the best tools for search keyword.
19:goooooogle yes!
如果想要找出g
开头与g
结尾的行,当中的字符可有可无:
# grep -n 'g.*g' regular_express.txt
1:"Open Source" is a good mechanism to develop programs.
14:The gd software is a library for drafting programs.
18:google is the best tools for search keyword.
19:goooooogle yes!
20:go! go! Let's go.
因为是g
开头与g
结尾,中间任意字符均可接受,.*
的RE表示任意字符是很常见的.
如果想要找出含有任意数字
的行:
# grep -n '[0-9][0-9]*' regular_express.txt
限定连续RE字符范围{}
我们可以利用.
与*
来配置0个到无限多个重复字符,那如果我想要限制一个范围区间内的重复字符呢?
举例来说,我们想要找出2个到5个o
的连续字串,该如实现?
这时候就得要使用到限定范围的字符{}
了,但因为{
与}
的符号在shell里有特殊意义的,因此我们必须要使用转义字符\
才行.
# grep -n 'o\{2,5\}' regular_express.txt
如果我们要找出g
后面接2到5o
,然后再接一个g
的字符串:
# grep -n 'go\{2,5\}g' regular_express.txt
18:google is the best tools for search keyword.
如果我想要的是2个o
以上的goooo....g
呢?除了可以是gooo*g
,也可以是:
[root@www ~]# grep -n 'go\{2,\}g' regular_express.txt
扩展grep(grep -E
或egrep
)
使用扩展grep的主要好处是增加了额外的正则表达式元字符集
打印所有包含NW
或EA
的行。如果不使用egrep
,而是grep
,将不会有结果查出:
# egrep 'NW|EA' testfile
northwest NW Charles Main 3.0 .98 3 34
eastern EA TB Savage 4.4 .84 5 20
对于标准grep,如果在扩展元字符前面加\
,grep会自动启用扩展选项-E
:
#grep 'NW\|EA' testfile
northwest NW Charles Main 3.0 .98 3 34
eastern EA TB Savage 4.4 .84 5 20
搜索所有包含一个或多个3的行:
# egrep '3+' testfile
# grep -E '3+' testfile
# grep '3\+' testfile
搜索所有包含0个或1个小数点字符的行:
# egrep '2\.?[0-9]' testfile
# grep -E '2\.?[0-9]' testfile
# grep '2\.\?[0-9]' testfile
#首先含有2字符,其后紧跟着0个或1个点,后面再是0和9之间的数字.
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
eastern EA TB Savage 4.4 .84 5 20
搜索一个或者多个连续的no的行
# egrep '(no)+' testfile
# grep -E '(no)+' testfile
# grep '\(no\)\+' testfile
#3个命令返回相同结果
northwest NW Charles Main 3.0 .98 3 34
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
不使用正则表达式(fgrep
或grep -E
)
fgrep
查询速度比grep
命令快,但是不够灵活:它只能找固定的文本,而不是正则表达式
如果你想在一个文件或者输出中找到包含星号字符的行:
fgrep '*' /etc/profile
或
grep -F '*' /etc/profile