Linux文本處理三劍客之---grep
grep: Global search REgular expression and Print out the line
作用:文本搜索工具,根據用戶指定的“模式”對目標文本逐行進行匹配檢查;打印匹配到的行
模式:由正則表達式字符及文本字符所編寫的過濾條件
1、命令格式
grep [OPTIONS] PATTERN [FILE...]
grep root /etc/passwd
grep "$USER" /etc/passwd
grep '$USER' /etc/passwd
grep `whoami` /etc/passwd
[root@centos7 ~]#grep root /etc/passwd #直接使用字符串過濾
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep "$USER" /etc/passwd #通過變量過濾
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep $USER /etc/passwd #使用變量過濾(不加雙引號)
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep `whoami` /etc/passwd #使用命令過濾(``)
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
2、grep命令選項:
參數 | 描述 |
--color=auto | 對匹配到的文本著色顯示 |
-v | 顯示不被pattern匹配到的行 |
-i | 忽略字符大小寫 |
-n | 顯示匹配的行號 |
-c | 統計匹配的行數 |
-o | 僅顯示匹配到的字符串 |
-q | 靜默模式,不輸出任何信息 |
-A # | after, 後#行 |
-B # | before, 前#行 |
-C # | context, 前後各#行 |
-e | 實現多個選項間的邏輯or關系 |
-w | 匹配整個單詞 |
-E | 使用ERE grep –e ‘cat ’ -e ‘dog’ file |
-F | 相當於fgrep,不支持正則表達式 |
-f:FILE, --file=FILE | 文件包含某字符串 Obtain patterns from FILE, one per line. |
例子:
[root@centos7 ~]#grep -v "root" /etc/passwd #-v過濾掉root行
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@centos7 ~]#grep -i "root" /etc/passwd #-i不區分大小寫
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep -ni "root" /etc/passwd #既顯示行號又不區分大小寫
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#cat -n /etc/passwd|grep root #等同於grep -ni “root” /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
10 operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#ls|grep ks
anaconda-ks.cfg
initial-setup-ks.cfg
[root@centos7 ~]#ls *ks*
anaconda-ks.cfg initial-setup-ks.cfg
[root@centos7 ~]#grep -ci "root" /etc/passwd #統計匹配到的行數
2
[root@centos7 ~]#grep -io "ROOT" /etc/passwd #不區分大小寫,僅顯示匹配到的字符串
root
root
root
root
[root@centos7 ~]#grep -cio "ROOT" /etc/passwd #統計僅顯示匹配的字符不區分大小寫
2
[root@centos7 ~]#grep -nA3 "root" /etc/passwd #顯示匹配到行之後n行
1:root:x:0:0:root:/root:/bin/bash
2-bin:x:1:1:bin:/bin:/sbin/nologin
3-daemon:x:2:2:daemon:/sbin:/sbin/nologin
4-adm:x:3:4:adm:/var/adm:/sbin/nologin
--
10:operator:x:11:0:operator:/root:/sbin/nologin
11-games:x:12:100:games:/usr/games:/sbin/nologin
12-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13-nobody:x:99:99:Nobody:/:/sbin/nologin
[root@centos7 ~]#grep -nB3 "root" /etc/passwd #顯示匹配到行之前n行
1:root:x:0:0:root:/root:/bin/bash
--
7-shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8-halt:x:7:0:halt:/sbin:/sbin/halt
9-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep -nC3 "root" /etc/passwd #顯示匹配到行之前後n行
1:root:x:0:0:root:/root:/bin/bash
2-bin:x:1:1:bin:/bin:/sbin/nologin
3-daemon:x:2:2:daemon:/sbin:/sbin/nologin
4-adm:x:3:4:adm:/var/adm:/sbin/nologin
--
7-shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8-halt:x:7:0:halt:/sbin:/sbin/halt
9-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/root:/sbin/nologin
11-games:x:12:100:games:/usr/games:/sbin/nologin
12-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13-nobody:x:99:99:Nobody:/:/sbin/nologin
[root@centos7 ~]#grep root /etc/passwd|grep bash #|並且關系
root:x:0:0:root:/root:/bin/bash
[root@centos7 ~]#grep -e root -e bash /etc/passwd #-e或者關系
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rick:x:1000:1000:rick:/home/rick:/bin/bash
mage:x:1001:1001::/home/mage:/bin/bash
wang:x:1002:1004::/home/wang:/bin/bash
tom:x:1003:1005::/home/tom:/bin/bash
[root@centos7 ~]#echo xabcy|grep abc #匹配包含abc字符串
xabcy
[root@centos7 ~]#echo xabcy|grep -w abc #匹配整個單詞
[root@centos7 ~]#echo "x abc y"|grep -w abc #單詞前後有空格可以匹配
x abc y
[root@centos7 ~]#echo "x,abc,y"|grep -w abc #單詞前後有逗號可以匹配
x,abc,y
[root@centos7 ~]#echo "x2abc3y"|grep -w abc #單詞前後有數字不能匹配到
[root@centos7 ~]#echo "x_abc_y"|grep -w abc #單詞前後有下劃線不能匹配到
[root@centos7 ~]#echo "x-abc-y"|grep -w abc #單詞前後有橫杠可以匹配
x-abc-y
總結:
grep過濾出單詞時,單一字母,數字加字母,下劃線加字母屬於單詞,其他符號都屬於不同單詞
[root@centos7 ~]#cat >p.txt #自定義字符串
root
bash
[root@centos7 ~]#cat p.txt
root
bash
[root@centos7 ~]#grep -f p.txt /etc/passwd #-f包含某字符關系
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rick:x:1000:1000:rick:/home/rick:/bin/bash
mage:x:1001:1001::/home/mage:/bin/bash
wang:x:1002:1004::/home/wang:/bin/bash
tom:x:1003:1005::/home/tom:/bin/bash
3、正則表達式
REGEXP:由一類特殊字符及文本字符所編寫的模式,其中有些字符(元字符)不表示字符字面意義,而表示控制或通配的功能
3.1、程序支持:grep,sed,awk,vim, less,nginx,varnish等
3.2、分兩類:
基本正則表達式:BRE
擴展正則表達式:ERE
grep -E, egrep
正則表達式引擎:
采用不同算法,檢查處理正則表達式的軟件模塊
PCRE(Perl Compatible Regular Expressions)
3.3、元字符分類:字符匹配、匹配次數、位置錨定、分組
3.4、man 7 regex
3.2.1、基本正則表達式元字符
通匹配符: *,?,[:digit:]:這些通配符表示文件名
正則表達式元字符:表示文件內容的字符串
3.2.2、egrep及擴展的正則表達式
egrep = grep -E
egrep [OPTIONS] PATTERN [FILE...]
1、擴展正則表達式的元字符:
1)字符匹配:
. 任意單個字符
[] 指定範圍的字符
[^] 不在指定範圍的字符
2、擴展正則表達式
1)次數匹配:
*:匹配前面字符任意次
?: 0或1次
+:1次或多次
{m}:匹配m次
{m,n}:至少m,至多n次
2)位置錨定:
^ :行首
$ :行尾
\<, \b :語首
\>, \b :語尾
3)分組:
()
後向引用:\1, \2, ...
4)或者:
a|b: a或b
C|cat: C或cat
(C|c)at:Cat或cat
3.3.1、字符匹配
選項:
符號 | 描述 |
. | 匹配任意單個字符(“.”點號在中括號[]表示本身意義) |
[] | 匹配指定範圍內的任意單個字符 |
[^] | 匹配指定範圍外的任意單個字符 |
[:alnum:] | 字母和數字 |
[:alpha:] | 代表任何英文大小寫字符,亦即 A-Z, a-z |
[:lower:] | 小寫字母 [:upper:] 大寫字母 |
[:blank:] | 空白字符(空格和制表符) |
[:space:] | 水平和垂直的空白字符(比[:blank:]包含的範圍廣) |
[:cntrl:] | 不可打印的控制字符(退格、刪除、警鈴...) |
[:digit:] | 十進制數字 [:xdigit:]十六進制數字 |
[:graph:] | 可打印的非空白字符 |
[:print:] | 可打印字符 |
[:punct:] | 標點符號 |
例子:
[root@centos7 ~]#echo abbc|grep a.c
[root@centos7 ~]#echo abbc|grep a..c
abbc
[root@centos7 ~]#echo ab我c|grep a..c
ab我c
提示:漢字也表示一個字符不是一個字節
[root@centos7 ~]#echo axcdef|grep "a[xyz]c" #匹配中括號中任意字符串
axcdef
[root@centos7 ~]#echo azcdef|grep "a[xyz]c" #匹配中括號中任意字符串
azcdef
[root@centos7 ~]#echo abcdef|grep "a[^xyz]c" #匹配不以中括號裏字符串
abcdef
3.3.2、匹配次數
用在要指定次數的字符後面,用於指定前面的字符要出現的次數
符號 | 描述 |
* | 匹配前面的字符任意次,包括0次(貪婪模式:盡可能長的匹配) |
.* | 任意長度的任意字符 |
\? | 匹配其前面的字符0或1次 |
\+ | 匹配其前面的字符至少1次 |
\{n\} | 匹配前面的字符n次 |
\{m,n\} | 匹配前面的字符至少m次,至多n次 |
\{,n\} | 匹配前面的字符至多n次 |
\{n,\} | 匹配前面的字符至少n次 |
例子:
1)匹配默認字符和整體單詞匹配
[root@centos7 ~]#touch abc
[root@centos7 ~]#touch xyz
[root@centos7 ~]#ls|grep ... #匹配三個字符串
abc
anaconda-ks.cfg
Desktop
Documents
Downloads
initial-setup-ks.cfg
[root@centos7 ~]#ls|grep -w "..." #匹配整個單詞字符串
abc
abc.log
all.log
anaconda-ks.cfg
b.txt
df.log
initial-setup-ks.cfg
2)匹配前面字符任意次: *(包含0次)
[root@centos7 ~]#echo axb|grep ax*b #匹配重復x任意次,包含0次
axb
[root@centos7 ~]#echo ab|grep "ax*b" #匹配重復x任意次,包含0次
ab
[root@centos7 ~]#echo abb|grep "ax*b"
abb
[root@centos7 ~]#echo aab|grep "ax*b"
aab
[root@centos7 ~]#echo axxxxb|grep "ax*b"
axxxxb
[root@centos7 ~]#ls |grep ".*\.txt" #過濾出以任意字符的.txt文件
b.txt
linux.txt
mail.txt
[root@centos7 ~]#ls |grep -o "\.txt" #僅顯示匹配到的字符串
.txt
.txt
.txt
.txt
.txt
[root@centos7 ~]#cat google.txt
gooooooooooooooooooooooooooogle
gogle
ggle
goooooooooooooo00000000ooooogle
[root@centos7 ~]#grep google google.txt #僅顯示匹配到的字符串
[root@centos7 ~]#grep "go*gle" google.txt #匹配*前面字符串的任意次
gooooooooooooooooooooooooooogle
gogle
ggle
[root@centos7 ~]#grep "go\?gle" google.txt #匹配?前面字符串的0或1次
gogle
ggle
[root@centos7 ~]#grep "go.*gle" google.txt #匹配任意長度的字符串(不包含0次)
gooooooooooooooooooooooooooogle
gogle
goooooooooooooo00000000ooooogle
[root@centos7 ~]#grep "go\+gle" google.txt #匹配\+前面字符至少1次
gooooooooooooooooooooooooooogle
goggle
[root@centos7 ~]#grep "go\{27\}gle" google.txt #匹配前面字符n次
gooooooooooooooooooooooooooogle
[root@centos7 ~]#grep "go\{20,\}gle" google.txt #匹配前面字符至少n次
gooooooooooooooooooooooooooogle
[root@centos7 ~]#grep "go\{20,30\}gle" google.txt #匹配前面字符至少m次,至多n次
gooooooooooooooooooooooooooogle
[root@centos7 ~]#grep "go\{0,\}gle" google.txt #匹配前面字符至少0次
gooooooooooooooooooooooooooogle
gogle
ggle
[root@centos7 ~]#grep "go*gle" google.txt #匹配前面字符任意次
gooooooooooooooooooooooooooogle
gogle
ggle
[root@centos7 ~]#grep "go\{,30\}gle" google.txt #匹配前面字符至多n次
gooooooooooooooooooooooooooogle
gogle
ggle
3.3.3、位置錨定:定位出現的位置
選項:
符號 | 描述 |
^ | 行首錨定,用於模式的最左側 |
$ | 行尾錨定,用於模式的最右側 |
^PATTERN$ | 用於模式匹配整行 |
^$ | 空行 |
^[[:space:]]*$ | 空白行 |
\< 或 \b | 詞首錨定,用於單詞模式的左側 |
\> 或 \b | 詞尾錨定;用於單詞模式的右側 |
\<PATTERN\> | 匹配整個單詞 |
例子:
1)根據行首行尾某字符進行匹配
[root@centos7 ~]#grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep "^root" /etc/passwd #以root開頭進行匹配
root:x:0:0:root:/root:/bin/bash
[root@centos7 ~]#grep "bash$" /etc/passwd #以bash結尾進行匹配
root:x:0:0:root:/root:/bin/bash
rick:x:1000:1000:rick:/home/rick:/bin/bash
mage:x:1001:1001::/home/mage:/bin/bash
wang:x:1002:1004::/home/wang:/bin/bash
tom:x:1003:1005::/home/tom:/bin/bash
2)過慮空行,只顯示非空行
[root@centos7 ~]#cat -A f1
$
$
^I$
aa $
bb$
[root@centos7 ~]#grep -v "^$" f1|grep -v "^[[:space:]]" #先過濾以空行開頭再過濾以空格與TAB行開頭
aa
bb
[root@centos7 ~]#grep -v "^[[:space:]]*$" f1 #直接使用以[:space:]開頭重復多次結尾過濾
aa
bb
3)確定某字符串出現位置
[root@centos7 ~]#grep "\<root" /etc/passwd #以root單詞左側開始匹配
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rooter:x:1004:1006::/home/rooter:/bin/bash
[root@centos7 ~]#useradd admroot #添加用戶admroot
[root@centos7 ~]#grep "root\>" /etc/passwd #以root單詞右側開始匹配
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
admroot:x:1005:1007::/home/admroot:/bin/bash
4)匹配整個單詞
[root@centos7 ~]#grep "\<root\>" /etc/passwd #匹配root整個單詞
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep "\broot\b" /etc/passwd #匹配root整個單詞
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos7 ~]#grep -w "root" /etc/passwd #-w匹配某個單詞
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
3.3.4、分組模式
1、分組:\(\) 將一個或多個字符捆綁在一起,當作一個整體進行處理,如:\(root\)\+
分組括號中的模式匹配到的內容會被正則表達式引擎記錄於內部的變量中,這些變量的命名方式為
: \1, \2, \3, ...
\1 表示從左側起第一個左括號以及與之匹配右括號之間的模式所匹配到的字符
示例: \(string1\+\(string2\)*\)
\1 :string1\+\(string2\)*
\2 :string2
2、後向引用:引用前面的分組括號中的模式所匹配字符,而非模式本身
3、或者:\|
示例:a\|b: a或b C\|cat: C或cat \(C\|c\)at:Cat或cat
例子:
1)將一個或多個字符捆綁成一個整體:
[root@centos7 ~]#echo wangwangwang|grep "wang\{3\}" #沒有匹配到3次g字符串
[root@centos7 ~]#echo wanggg|grep "wang\{3\}" #對g字符串匹配3次,而不是wang匹配3次
wanggg
[root@centos7 ~]#echo wangwangwang|grep "\(wang\)\{3\}" #將wang加括號當成整體匹配3次
wangwangwang
2)後向引用
[root@centos7 ~]#echo wangwangwangxxxxwangwangwang|grep "\(wang\)\{3\}.*\(wang\)\{3\}" #前後分組匹配wang單詞3次
wangwangwangxxxxwangwangwang
[root@centos7~]#echo wangwangwangxxxxwangwangwang|grep "\(wang\)\{3\}.*\1" #經過分組匹配字符,再通過後向引用取出
wangwangwangxxxxwangwangwang
[root@centos7 ~]#echo wangwangwangxxxxmagemagewangwangwangmagemagemage|grep "\(wang\)\{3\}.*\(mage\)\+\1.*\2" #嵌套分組匹配
wangwangwangxxxxmagemagewangwangwangmagemagemage
#\1表示\(wang\)匹配正則表達式
#\2表示對應\(mage\)匹配正則表達式
[root@centos7 ~]#echo rootxxrbbt|grep "\(r..t\).*\1" #\1與分組括號匹配字符不相同
[root@centos7 ~]#echo rootxxroot|grep "\(r..t\).*\1" #\1與分組括號匹配字符相同
rootxxroot
[root@centos7 ~]#echo rootxxrbbt|grep "\(r..t\).*\(r..t\)" #這種方式第1個分組與第2個分組匹配字符按照括號裏“..”來匹配最終字符串
rootxxrbbt
練習:
取出/etc/passwd行首單詞與行尾單詞相同
[root@centos7 ~]#useradd -s /bin/ahaha haha
[root@centos7 ~]#grep "^\(.*\):.*\1$" /etc/passwd #匹配首尾單詞不嚴謹
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
bash:x:1006:1008::/home/bash:/bin/bash
haha:x:1007:1009::/home/haha:/bin/ahaha #註意:行首與行尾匹配不相同,也被取出
[root@centos7 ~]#grep "^\(.*\):.*\/\1$" /etc/passwd #標準匹配首尾單詞一致
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
bash:x:1006:1008::/home/bash:/bin/bash
3)或關系匹配
示例:
a\|b:a或b
C\|cat:C或cat
\(C|c\)at:Cat或cat
例子:
[root@centos7 ~]#grep "^a\|^b.*" /etc/passwd #匹配a開頭字符串的行,而b匹配以b開頭後面接任意字符串的行
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
admroot:x:1005:1007::/home/admroot:/bin/bash
bash:x:1006:1008::/home/bash:/bin/bash
[root@centos7 ~]#grep "^\(a\|b\).*" /etc/passwd #匹配以a或b開頭後面接任意字符串的行
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
admroot:x:1005:1007::/home/admroot:/bin/bash
bash:x:1006:1008::/home/bash:/bin/bash
[root@centos7 ~]#echo abc|grep "^a"
abc
[root@centos7 ~]#echo aaaa|grep "a\|b"
aaaa
[root@centos7 ~]#echo bbb|grep "a\|b" #匹配a或b字符串
bbb
[root@centos7 ~]#echo axy|grep "a\|bxy" #匹配a或bxy字符串
axy
[root@centos7 ~]#echo axy|grep "\(a\|b\)xy" #匹配axy或bxy字符串
axy
練習:僅限使用grep實現
1、取網卡IP
2、取分區利用率最大值
3、判斷OS主版本號(通用命令)
Linux文本處理三劍客之---grep