linux中grep命令的用法
grep說明
作爲linux中最爲常用的三大文本(awk,sed,grep)處理工具之一,掌握好其用法是很有必要的。
首先談一下grep命令的常用格式爲:grep [選項] ”模式“ [文件]
grep家族總共有三個:grep,egrep,fgrep。
常用選項
語法:grep [選項]
--v
:(等同於–version):查看版本
-E
:開啓擴展(Extend)的正則表達式。
-i
:忽略大小寫(ignore case)。
-v
:反過來(invert),只打印沒有匹配的,而匹配的反而不打印。
-q
:安靜。不向標準輸出寫任何東西。如果找到任何匹配的內容就立即以狀態值 0
-n
:顯示行號
-w
:被匹配的文本只能是單詞,而不能是單詞中的某一部分,如文本中有liker,而我搜尋的只是like,就可以使用-w選項來避免匹配liker
-c
:顯示總共有多少行被匹配到了,而不是顯示被匹配到的內容,注意如果同時使用-cv選項是顯示有多少行沒有被匹配到。
-o
:只顯示被模式匹配到的字符串。
--color
:將匹配到的內容以顏色高亮顯示。
-A n
:顯示匹配到的字符串所在的行及其後n行,after
-B n
:顯示匹配到的字符串所在的行及其前n行,before
-C n
:顯示匹配到的字符串所在的行及其前後各n行,context
[root@control ~]$grep --v #查看版本
grep (GNU grep) 2.20
Copyright (C) 2014 Free Software Foundation, Inc.
[root@control ~]$grep --version #查看版本
grep (GNU grep) 2.20
Copyright (C) 2014 Free Software Foundation, Inc.
[root@control ~]$
[root@control ~]$grep ccx /etc/passwd #普通查找
ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
ccx1:x:1001:1001::/home/ccx1:/bin/bash
ccx2:x:1002:1002::/home/ccx2:/bin/bash
ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]$
[root@control ~]$grep -i CCx /etc/passwd #忽略大小寫
ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
ccx1:x:1001:1001::/home/ccx1:/bin/bash
ccx2:x:1002:1002::/home/ccx2:/bin/bash
ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]$
[root@control ~]$cat a #測試文本
root
ccx
hero
[root@control ~]$grep -v root a #過濾root
ccx
hero
[root@control ~]$
[root@control ~]$grep -q ccx /etc/passwd #不會打印內容,即使ccx存在
[root@control ~]$echo $? #返回0就是說明上上面-q有內容,一般用於腳本中返回判斷條件用
0
[root@control ~]$grep -q ccxcxxc /etc/passwd # 這個ccxcxxc明顯不存在
[root@control ~]$echo $? #所以返回1
1
[root@control ~]$
[root@control ~]$grep -n ccx /etc/passwd #顯示行號
42:ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
46:ccx1:x:1001:1001::/home/ccx1:/bin/bash
47:ccx2:x:1002:1002::/home/ccx2:/bin/bash
48:ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]$grep -nw ccx /etc/passwd #-w精確查找
42:ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
[root@control ~]$
[root@control ~]$grep -c ccx /etc/passwd #僅顯示匹配到的行數
4
[root@control ~]$grep -on ccx /etc/passwd# 僅顯示匹配到的內容,也就是該文中所有ccx,結合n更直觀
42:ccx
42:ccx
42:ccx
46:ccx
46:ccx
47:ccx
47:ccx
48:ccx
48:ccx
[root@control ~]$
[root@control ~]$cat a#測試文檔
root
ccx
hero
go fot it
just
do
it
[root@control ~]$grep -nA 2 ccx a #打印關鍵字後兩行,有時候在腳本中篩選比awk還好用,記住ABC的使用方法
2:ccx
3-hero
4-go fot it
[root@control ~]$grep -nB 2 go a #打印關鍵字前2行
2-ccx
3-hero
4:go fot it
[root@control ~]$grep -nC 2 go a #打印關鍵字前後2行
2-ccx
3-hero
4:go fot it
5-just
6-do
[root@control ~]$
模式部分
1、直接輸入要匹配的字符串,這個可以用fgrep(fast grep)
代替來提高查找速度,比如我要匹配一下hello.c文件中printf的個數:fgrep -c "printf" hello.c
2、使用基本正則表達式,下面談關於基本正則表達式的使用:
匹配字符:
.
:任意一個字符。
[abc]
:表示匹配一個字符,這個字符必須是abc中的一個。
[a-zA-Z]
:表示匹配一個字符,這個字符必須是a-z或A-Z這52個字母中的一個。
[^123]
:匹配一個字符,這個字符是除了1、2、3以外的所有字符。
對於一些常用的字符集,系統做了定義:
[A-Za-z]
等價於 [[:alpha:]]
[0-9]
等價於 [[:digit:]]
[A-Za-z0-9]
等價於 [[:alnum:]]
tab,space
等空白字符 [[:space:]]
[A-Z]
等價於 [[:upper:]]
[a-z]
等價於 [[:lower:]]
,.:等
標點符號[[:punct:]]
[root@control ~]$grep ro.. /etc/passwd #ro.. 表示ro後面要有2個任意字母
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
systemd-bus-proxy:x:999:998:systemd Bus Proxy:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
chrony:x:992:989::/var/lib/chrony:/sbin/nologin
setroubleshoot:x:991:988::/var/lib/setroubleshoot:/sbin/nologin
dockerroot:x:989:984:Docker User:/var/lib/docker:/sbin/nologin
[root@control ~]$grep cc[xyz] /etc/passwd #ccx後面必須是xyz中的一個
ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
ccx1:x:1001:1001::/home/ccx1:/bin/bash
ccx2:x:1002:1002::/home/ccx2:/bin/bash
ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]$grep cc[^xyz] /etc/passwd #ccx後面除了xyz的任意字母
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
libstoragemgmt:x:996:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
[root@control ~]$grep 10[0-9] /etc/passwd #10後面跟一個0-9的數字
games:x:12:100:games:/usr/games:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
ccx1:x:1001:1001::/home/ccx1:/bin/bash
ccx2:x:1002:1002::/home/ccx2:/bin/bash
ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]$grep 10[0-9][0-9] /etc/passwd #10後面跟2個0-9的數字
ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
ccx1:x:1001:1001::/home/ccx1:/bin/bash
ccx2:x:1002:1002::/home/ccx2:/bin/bash
ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]$grep : /etc/passwd # 符號這直接替換爲 想要篩選的符號即可
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
匹配次數(篩選)
一個正則表達式後面可以跟隨多種重複操作符之一,主要是用來匹配任意字符出現的次數!
{}的符號在shell有特殊意義,因此要用到轉義字符\
。
?
先前的項是可選的,最多匹配一次,等價於{0,1}。
*
先前的項可以匹配零次或多次,等價於{0,},所以 "." 表述任意字符任意次,即無論什麼內容全部匹配。
+
先前的項可以匹配一次或多次。
"x\{n\}y"
x是代表需要出現次數的任意字符,y是後面需要跟的任意字符(可選項,也可以用),先前x的項將匹配恰好 n 次。
"x\{n,\}y"
x是代表需要出現次數的任意字符,y是後面需要跟的任意字符(可選項,也可以用*),先前的項可以匹配 n 或更多次。
"x\{n,m\}y"
x是代表需要出現次數的任意字符,y是後面需要跟的任意字符(可選項,也可以用*),先前的項將匹配至少 n 次,但是不會超過 m 次。
注:上面的x和y均可以套入正則,如[A-Z],y是可選項,但也可以套入正則,如[A-Z],但如果x不滿足條件,y是沒有意義的。
[root@control ~]$grep -n "\/*sh" /etc/passwd #\轉義/,等同於grep "/.*sh" /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
33:setroubleshoot:x:991:988::/var/lib/setroubleshoot:/sbin/nologin
37:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
42:ccx:x:1000:1000:ccx:/home/ccx:/bin/bash
43:apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
44:tomcat:x:53:53:Apache Tomcat:/usr/share/tomcat:/sbin/nologin
46:ccx1:x:1001:1001::/home/ccx1:/bin/bash
47:ccx2:x:1002:1002::/home/ccx2:/bin/bash
48:ccx3:x:1003:1003::/home/ccx3:/bin/bash
[root@control ~]
[root@control ~]$cat a
root
ccx
hero
go fot it
just
do
it
2020 years
05 mon
[root@control ~]$grep "[0-9]\{2\}" a # 我懷疑我係統有問題,按理說不應該出現2020的,注意這個問題!
2020 years
05 mon
[root@control ~]$grep -o "[0-9]\{2,3\}" a #如果要精確 就需要 -o 參數,但這樣就不是整行內容了。
202
05
[root@control ~]$grep "[0-9]\{3,4\}" a #0-9出現3或4次,這個對了
2020 years
[root@control ~]$grep "c\{2\}" a #字符c出現2次,這也沒問題。
ccx
[root@control ~]$
位置錨定
^x
:錨定行首,x代表任意字符。
x$
:錨定行尾,x代表任意字符。技巧:^$
用於匹配空白行,所以grep -v ^$
就是過濾空白行
"\bx或\<"
:錨定單詞的詞首,x代表任意字符。如"\blike"不會匹配alike,但是會匹配liker
"x\b或\>"
:錨定單詞的詞尾,x代表任意字符。如"like\b"不會匹配alike,但是會匹配liker
"\bx\b"
:篩選固定單詞,x代表任意字符(必須是一個完整的單詞,不能是一個單詞的一部分)。如"\blike\b"不會匹配alike和liker,只會匹配like
"\B"
:與\b作用相反。
[root@control ~]$cat a
root
ccx
hero
go fot it
just
do
it
2020 years
05 mon
[root@control ~]$grep ^c a#c開頭
ccx
[root@control ~]$grep x$ a #x結尾
ccx
[root@control ~]$grep -v "^$" a #過濾空白行
root
ccx
hero
go fot it
just
do
it
2020 years
05 mon
[root@control ~]$grep "\bc" a #c開頭
ccx
[root@control ~]$grep "s\b" a #b結尾
2020 years
[root@control ~]$grep "\bcx\b" a #只有ccx沒有cx這個單詞,不能爲單詞的一部分,如下面的ccx可以正常篩選
[root@control ~]$grep "\bccx\b" a # 固定篩選ccx
ccx
[root@control ~]$
分組及引用
\(string\)
:將string作爲一個整體方便後面引用
\1
:引用第1個左括號及其對應的右括號所匹配的內容。
\2
:引用第2個左括號及其對應的右括號所匹配的內容。
\n
:引用第n個左括號及其對應的右括號所匹配的內容。
[root@control ~]$grep "^\([[:alpha:]]\).*\1$" /etc/passwd #開頭和結尾相同字母的行
nobody:x:99:99:Nobody:/:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
[root@control ~]$
過濾IP代碼分解
說明
篩選IP 首先你得知道 你的IP是配置在哪個網卡的,如果有多個bond,你要知道自己想篩選哪個bond的IP。
查看方式有很多,這裏說3種吧!
- 第一種
這種方法適用於你知道網卡(ip配在哪個網卡中)。
去網絡配置文件中查看網卡,網絡配置文件 /etc/sysconfig/network-scripts/ifcfg-ens33(網卡名稱)
egrep 篩選ip代碼塊(下面會說代碼的) /etc/sysconfig/network-scripts/ifcfg-ens160(網卡名稱)
- 第二種
和第一種方式一樣,你得知道你ip配在哪個網卡中,只是這不用去配置文件裏查看,稍微簡單些。
ip a show 網卡名稱 | egrep 篩選ip代碼塊(下面會說代碼的)
- 第三種
這種就是你不必去查ip配在哪個網卡上的,只需要知道,ip段即可! ifconfig 和 ip a 相同。
ifconfig | egrep 篩選ip代碼塊(下面會說代碼的)| grep ip段(比如0.0)
代碼
代碼分解
先來康康,檢索出 0-299(其實到255就可以了,但我想提高到299,反正也沒壞處)的範圍代碼:egrep '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])'
(這裏()
可以不需要加,但爲了養成好習慣,加上吧)
實現原理:|
在這起分割作用,具體的我就不做解釋了。 [0-9]
提取個位數,[1-9][0-9]
提取10-99,1[0-9][0-9]
提取100-199的數,2[0-9][0-9]
提取200-299的數
全部代碼
- 完整代碼
egrep '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\>'
- 原理:
\<和 \>
是精確查找,等同於"\bx\b"
,不明白的看上面位置錨定的說明。
\.
就是轉義後.
的意思。
(檢索出 0-299代碼)\.(檢索出 0-299代碼)\.(檢索出 0-299代碼)\.(檢索出 0-299代碼)
因爲IP是由3個.
隔開的4串數字,這是固定的。
[root@control network-scripts]$cat ifcfg-ens160 | egrep '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\>'
#DNS1=10.233.3.225
IPADDR=10.233.3.225
GATEWAY=10.233.3.254
- 簡化代碼
其實也就是相同的代碼用{3}
替代而已,建議瞭解就好,沒必要爲了少些點代碼,把自己攪暈了。
這裏放完整版代碼和簡化代碼你對比一下吧!
完整版:
egrep '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\>'
簡化版:
egrep '\<(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\>'
[root@control network-scripts]$ifconfig | egrep '\<(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\>'
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet 10.233.3.225 netmask 255.255.255.128 broadcast 10.233.3.255
inet 127.0.0.1 netmask 255.0.0.0
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
[root@control network-scripts]$
提取ip
既然說到 ip篩選了,順便說說,提取ip,這裏用上面的方法三做說明,除了egrep以外還需要用到 awk。
[root@control network-scripts]$ifconfig | egrep '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])\>'|grep 10.233|awk '{print $2}'
10.233.3.225
[root@control network-scripts]$