Linux (三劍客之一) grep字串搜尋命令詳解

openbox2008發表於2018-06-07
(1)grep命令簡介

    Linux系統中grep命令是一種強大的文字搜尋工具,它能使用正規表示式搜尋文字,並把匹 配的行列印出來。grep全稱是Global Regular Expression Print,表示全域性正規表示式版本,它的使用許可權是所有使用者。
    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的功能。


(2)grep命令格式
grep能夠快速的對檔案進行搜尋,命令和引數都比較好理解:

grep [-acinv] [--color=auto] '搜尋字串' filename1 filename2 可以在多個檔案中搜尋
選項與引數:

-a :將 binary 檔案以 text 檔案的方式搜尋資料
-c :計算找到 '搜尋字串' 的次數
-i :忽略大小寫的不同,所以大小寫視為相同
-n :順便輸出行號
-v :反向選擇,亦即顯示出沒有 '搜尋字串' 內容的那一行!

--color=auto :可以將找到的關鍵詞部分加上顏色的顯示喔!


1.例:輸出帶行號,-n輸出行號,-c統計搜尋到的行數
[root@network1 ~]# grep  -n sed linux-auto-init.sh  
24:sed -i 's/ONBOOT=no/ONBOOT=yes/' /etc/sysconfig/network-scripts/ifcfg-em2 
25:sed -i 's/BOOTPROTO=dhcp/BOOTPROTO=static/' /etc/sysconfig/network-scripts/ifcfg-em2 
26:sed -i '/NETBOOT=yes/d' /etc/sysconfig/network-scripts/ifcfg-em2 

2.例:在多個檔案中搜尋,-v表示反向搜尋

[root@computer1 ~]# grep -v "#" linux-auto-init.sh test.sh 
linux-auto-init.sh:
linux-auto-init.sh:init_name="network1"
linux-auto-init.sh:init_ip="172.16.70.71"
linux-auto-init.sh:hostnamectl set-hostname ${init_name}

詳細選項:

-a 不要忽略二進位制資料。
-A<顯示列數> 除了顯示符合範本樣式的那一行之外,並顯示該行之後的內容。
-b 在顯示符合範本樣式的那一行之外,並顯示該行之前的內容。
-c 計算符合範本樣式的列數。
-C<顯示列數>或-<顯示列數>  除了顯示符合範本樣式的那一列之外,並顯示該列之前後的內容。
-d<進行動作> 當指定要查詢的是目錄而非檔案時,必須使用這項引數,否則grep命令將回報資訊並停止動作。
-e<範本樣式> 指定字串作為查詢檔案內容的範本樣式。
-E 將範本樣式為延伸的普通表示法來使用,意味著使用能使用擴充套件正規表示式。
-f<範本檔案> 指定範本檔案,其內容有一個或多個範本樣式,讓grep查詢符合範本條件的檔案內容,格式為每一列的範本樣式。
-F 將範本樣式視為固定字串的列表。
-G 將範本樣式視為普通的表示法來使用。
-h 在顯示符合範本樣式的那一列之前,不標示該列所屬的檔名稱。
-H 在顯示符合範本樣式的那一列之前,標示該列的檔名稱。
-i 胡列字元大小寫的差別。
-l 列出檔案內容符合指定的範本樣式的檔名稱。
-L 列出檔案內容不符合指定的範本樣式的檔名稱。
-n 在顯示符合範本樣式的那一列之前,標示出該列的編號。
-q 不顯示任何資訊。
-R/-r 此引數的效果和指定“-d recurse”引數相同。
-s 不顯示錯誤資訊。
-v 反轉查詢。
-w 只顯示全字元合的列。
-x 只顯示全列符合的列。
-y 此引數效果跟“-i”相同。
-o 只輸出檔案中匹配到的部分。

3.多個搜尋條件-e,條件之間是或的關係
[root@computer1 ~]# grep -e '^[a-c]' -e "^sys" linux-auto-init.sh 
cat >/etc/sysconfig/network-scripts/ifcfg-em2 << END
systemctl restart network
cat >/etc/hosts << EOF
systemctl disable firewalld
systemctl stop firewalld

4.遞迴搜尋 -r,搜尋/etc/所有子目錄下以sys開頭的行
[root@computer1 /]# grep -r '^sys' /etc/
/etc/services:syslog-tls      6514/udp                # Syslog over TLS
/etc/services:syslog-tls      6514/dccp               # Syslog over TLS
/etc/services:sysinfo-sp      11967/tcp               # SysInfo Service Protocol
/etc/services:sysinfo-sp      11967/udp               # SysInfo Sercice Protocol
/etc/shadow:systemd-network:!!:17655::::::
/etc/rc.d/init.d/README:systemctl(1).
/etc/rc.d/init.d/README:system. An init script /etc/rc.d/init.d/foobar is implicitly mapped
/etc/rc.d/init.d/functions:systemctl_redirect () {
/etc/passwd-:systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin

#在目錄下,指定在xxx.xxx檔案中搜尋
grep  "ERROR"  /var/ -r --include "*.log"

#在搜尋結果中排除所有xxx.xxx檔案
grep "xxx" . -r --exclude "xxx.xxx"

[root@computer1 /]# grep  "ERROR"  /var/ -r --exclude "*.xml"
Binary file /var/lib/rpm/Packages matches
Binary file /var/lib/rpm/Basenames matches
Binary file /var/lib/rpm/__db.003 matches
Binary file /var/lib/mlocate/mlocate.db matches
/var/log/tuned/tuned.log:2018-05-04 10:04:20,644 ERROR    tuned.utils.commands: Executing x86_energy_perf_policy error: 
/var/log/tuned/tuned.log:2018-05-04 10:04:20,667 ERROR    tuned.utils.commands: Error when reading file '/sys/class/drm/card0/device/power_method': '[Errno 2] No such file or directory: u'/sys/class/drm/card0/device/power_method''
/var/log/tuned/tuned.log:2018-05-04 10:25:46,834 ERROR    tuned.utils.commands: Executing 

#在搜尋結果中排除filelist檔案列表裡的檔案
grep "xxx" . -r --exclude-from filelist

(3)作為命令的管道進行搜尋
在linux的命令中,有些命令顯示了大量的內容,不容易檢視可以通過grep過濾,得到想要的結果,如命令ps ax 顯示了大量的,使用grep過濾相關程式。

[root@controller1 ~]# ps aux | grep httpd
root        927  0.0  0.3 230228  5712 ?      Ss   May29   0:37 /usr/sbin/httpd -DFOREGROUND
apache    15129  0.0  0.3 232384  7096 ?        S    Jun04   0:04 /usr/sbin/httpd -DFOREGROUND
apache    15130  0.0  0.3 232384  7092 ?        S    Jun04   0:04 /usr/sbin/httpd -DFOREGROUND
apache    15131  0.0  0.3 232384  7092 ?        S    Jun04   0:03 /usr/sbin/httpd -DFOREGROUND


1.例:利用|,進行多層過濾
grep pattern1 files | grep pattern2 #注意格式,檔名跟在第一個grep後面
[root@computer1 ~]# grep ^[0-9] linux-auto-init.sh
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
172.16.100.70 controller1 
172.16.100.71 network1
172.16.100.72 compute1
172.16.100.73 compute2
172.16.100.74 compute3
172.16.100.90 block

[root@computer1 ~]# grep ^[0-9] linux-auto-init.sh |grep '70'
172.16.100.70 controller1 

[root@computer1 ~]# 

2.例:表示式裡面出現?+(){}| 特殊符號,需要用\轉義
如果不轉義,grep會出錯,或者使用egrep或grep -E,此處對|進行轉義,和例3中的egrep結果一樣
[root@computer1 ~]# grep "^s\|^[0-9]" linux-auto-init.sh 
sed -i 's/ONBOOT=no/ONBOOT=yes/' /etc/sysconfig/network-scripts/ifcfg-em2 
sed -i 's/BOOTPROTO=dhcp/BOOTPROTO=static/' /etc/sysconfig/network-scripts/ifcfg-em2 
sed -i '/NETBOOT=yes/d' /etc/sysconfig/network-scripts/ifcfg-em2 
systemctl restart network
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
172.16.100.70 controller1 
172.16.100.71 network1
172.16.100.72 compute1
systemctl disable firewalld
systemctl stop firewalld

3.例:egrep擴充套件過濾,'^[s]|^[0-9]'表示以s頭數字開頭的行
[root@computer1 ~]# egrep '^[s]|^[0-9]' linux-auto-init.sh 
sed -i 's/ONBOOT=no/ONBOOT=yes/' /etc/sysconfig/network-scripts/ifcfg-em2 
sed -i 's/BOOTPROTO=dhcp/BOOTPROTO=static/' /etc/sysconfig/network-scripts/ifcfg-em2 
sed -i '/NETBOOT=yes/d' /etc/sysconfig/network-scripts/ifcfg-em2 
systemctl restart network
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
172.16.100.70 controller1 
172.16.100.71 network1
172.16.100.72 compute1
systemctl disable firewalld

systemctl stop firewalld


4.例:grep表示式中|表示或的意思
如果要表達條件與,只能用grep pattern1 files | grep pattern2
[root@computer1 ~]# grep "IPADDR\|GATEWAY"  /etc/sysconfig/network-scripts/ifcfg-em2
IPADDR=172.16.70.72
GATEWAY=172.16.70.10

5.例:()內表示一組,(oo)表示兩oo一組,需要\轉義(){}
[root@computer1 ~]# grep "\(oo\)\{2,5\}g" test.sh  
goooooooooooooooogl
wooooogl

(4)grep正規表示式

grep的正則跟其他語言的正規表示式有一些不同,認識到grep裡的規則,就能容易寫出grep的過濾條件。
RE(正規表示式)

^ 匹配正規表示式的開始行
$ 匹配正規表示式的結束行
< 從匹配正規表示式的行開始
> 到匹配正規表示式的行結束
[ ] 單個字元;如[A] 即A符合要求
[ - ] 範圍 ;如[A-Z]即A,B,C一直到Z都符合要求

^[0-9] 以數字開始的行,[]內可列舉字母
^[124ab] 以1,2,4,a,或b開頭的行
^b.503 句點表示任一字母
* 星號表示0個以上的字母(可以沒有)
+ 加號表示1個以上的字母
. 表示一個任意字元

\反斜線,轉義符號,可以去掉特殊意義

1.例:[]表示範圍
比如[a-z] 表示小寫字母,[0-9] 表示0~9的數字, [A-Z] 則是大寫字母們。[a-zA-Z0-9]表示所有數字與英文字元。 
[root@controller1 ~]# grep -n '^[a-Z]' admin-openrc 
2:export OS_PROJECT_DOMAIN_NAME=Default
3:export OS_USER_DOMAIN_NAME=Default
4:export OS_PROJECT_NAME=admin
5:export OS_USERNAME=admin
6:export OS_PASSWORD=ADMIN_PASS
7:export OS_AUTH_URL=http://172.16.70.201:5000/v3
8:export OS_IDENTITY_API_VERSION=3

2.例:[]裡面的^和外面的^不同
[]裡面的^ :表示反,外面的^:表示從行首開始
[root@computer1 ~]# grep -n '^[^a-zA-Z]' linux-auto-init.sh 
1:#!/bin/bash
23:#2.自動配置第二塊網路卡資訊
51:#3.重啟網路服務
54:     systemctl restart network
56:    site="www.qq.com"  
57:    ping -c1 -W1  ${site} &> /dev/null  
68:#4.更改/etc/hosts檔案
70:127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
71:::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
72:172.16.100.70 controller1 
73:172.16.100.71 network1
74:172.16.100.72 compute1

3.例:'^$' 表示行首和行尾,即空行
搜尋空行
[root@computer1 ~]# grep -n '^$' linux-auto-init.sh 
8:
19:
22:

4.例:轉義符\ ,比如 '\.'
[root@computer1 ~]# grep -n '^[A-Z]' linux-auto-init.sh |grep '\.'   
45:NETMASK=255.255.255.0
46:GATEWAY=172.16.70.10
47:DNS1=202.96.128.166

48:DNS2=8.8.8.8

注意:此處grep -n '^[A-Z]' linux-auto-init.sh |grep '\.' (正確)和grep -n '^[A-Z]'|grep '\.' linux-auto-init.sh(錯誤)的區別。檔名,一定要跟在第一個grep 後面

5.例:[]中的^ - 不表現特殊意義,直接放在[]裡面內容的後面。
表示沒有字母,沒有#沒有空格,沒有:沒有!的串,注意[]裡面有個小空格。
[root@computer1 ~]# grep -n '^[^a-Z^# :!]' linux-auto-init.sh 
54:     systemctl restart network
70:127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
72:172.16.100.70 controller1 
73:172.16.100.71 network1
74:172.16.100.72 compute1
75:172.16.100.73 compute2
76:172.16.100.74 compute3
另外shell 裡面的反向選擇為[!range], 正則裡面是 [^range]

6.例:.號,找出p??l 的字串,亦即共有四個位元組,起頭是p而結束是l
[root@computer1 ~]# grep -n 'p..l' linux-auto-init.sh    
100:#server 0.centos.pool.ntp.org iburst
101:#server 1.centos.pool.ntp.org iburst
102:#server 2.centos.pool.ntp.org iburst
103:#server 3.centos.pool.ntp.org iburst

7.例:範圍 { } 限定連續重複字元
. * 只能限制0個或多個, 如果要確切的限制字元重複數量,就用{範圍} 。範圍是數字用,隔開 2,5 表示2~5個,
2表示2個,2, 表示2到更多個,注意,由於{ }在SHELL中有特殊意義,因此作為正規表示式用的時候要用\轉義一下。

#找到兩個連續o的字串
[root@computer1 ~]# grep -n 'o\{2\}' linux-auto-init.sh 
100:#server 0.centos.pool.ntp.org iburst
101:#server 1.centos.pool.ntp.org iburst
102:#server 2.centos.pool.ntp.org iburst

#找出1到2個o,後再接一個l的字串
[root@computer1 ~]# grep -n 'o\{1,2\}l' linux-auto-init.sh 
72:172.16.100.70 controller1 
100:#server 0.centos.pool.ntp.org iburst
101:#server 1.centos.pool.ntp.org iburst
102:#server 2.centos.pool.ntp.org iburst
103:#server 3.centos.pool.ntp.org iburst
107:#其他節點如下修改,採用controller的時鐘







相關文章