一文帶你搞懂grep的常用技巧(附帶分解版的篩選提取IP實驗)

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]$

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章