grep是linux上常用的一個文本處理工具之一。它有著強大的文本處理能力,學會它,可以讓工作更有效率。
一、初識grep
grep: Global search Regular Experssion and Print out line
從名字上也可以直觀的了解到它是基于正則表達式進行全局搜索,并把結果打印到屏幕上來。
說白了,它就是根據用戶指定的“模式(pattern)”來對文本進行過濾,并顯示匹配到的行的文本搜索工具。
二、何為“模式”
所謂模式,就是由一類字符書寫,但是這些字符不表示字符本身字面的意義,而是表示控制或通配的功能。它還有一個高雅的名字,即正則表達式。
三、了解正則表達式
1、基本的元字符
. 匹配任意的字符
* 匹配其前面的字符任意次數,0,1或多次
\? 匹配其前面的字符0次或1次
\+ 匹配其前面的字符1次以上
2、按字符匹配:
.: 匹配任意單個字符
[]: 匹配指定集合中的任意單個字符
常用的字符集合:
[[:digit:]],[0-9] 表示0-9的任意數字
[[:lower:]], [a-z] 表示26個小寫英文字母
[[:upper:]], [A-Z] 表示26個大寫英文字母
[[:alpha:]], [a-zA-Z] 表示所有英文字母
[[:alnum:]], [[0-9a-zA-Z] 表示數字,所有英文字母
[[:space:]] 表示空白字符
[[:punct:]] 表示符號字符
[^]: 匹配指定集合外的任意單個字符
3、按匹配次數匹配:
* : 匹配其前面任意字符任意次數
\?: 匹配其前面的字符0次或1次
\+: 匹配其前面的字符出現至少1次
\{m\}: 匹配其前面的字符出現m次
\{m,n\}: 匹配其前面的字符至少m次,至多n次
.* : 常用組合,表示任意長度的任意字符
4、實現位置錨定
^ : 寫在模式的最左側,表示錨定行首
$ : 寫在模式的最右側,表示錨定行尾
\<: 寫在要查找的單詞模式的左側,做單詞詞首錨定
\>: 寫在要查找的單詞模式的右側,做單詞詞尾錨定
^$: 常用組合,表示空白行
\<pattern\>: 匹配單詞
5、實現分組(只要功能可以用于實現后向引用)
\(\): 在模式中,如果使用了分組,在某行文本檢測中,如果\(\)匹配到了某內容,此內容可以在后面的模式中被引用。
\# : 引用之前被\(\)所匹配到的內容,模式自左而右,引用第#個左括號以及其匹配右括號之間的模式匹配到的內容。
三、grep命令
1、基本語法:
grep [OPTIONS] PATTERN [FILE…]
常用選項:
-i, –ignore-case : 忽略字符大小寫
-o, –only-matching : 只顯示被模式匹配到的內容
-v, –invert-match : 反向選取,顯示被模式匹配到的內容的相反內容
-A #,–after-context=#: 顯示被模式匹配到的行和此行之后的#行
-B #,–before-context=#: 顯示被模式匹配到的行和此行之前的#行
-C #,–context=#: 顯示被模式匹配到的行和此行前后的#行
-r, -R, –recursive: 遞歸查詢,對目錄下的子目錄也會進行查詢
-E, –extended-regexp: 使用擴展正則表達式進行匹配,相當于egrep
-F, –fixed-strings: 不使用正則表達式經行匹配,即忽略元字符的意義,相當于fgrep
–color={never,always,auto}:可以設置顏色顯示,可以進行別名,方便使用。例如:alias grep='grep –color=auto'
四、知識點練習
接下來我們以以下文本文件的內容來進行練習
練習1:顯示b出現3次以上的行
grep "b\{3,\}" test.txt
練習2:統計文本文件中work|WORK出現的次數
grep -i -o "\<work\>" test.txt | wc -l
練習3:顯示所有包含符號的行
grep "[[:punct:]]" test.txt
練習4:找出其中最后一個單詞是由此前某單詞加er構成的行。
grep "\(\<[[:alpha:]]\+\>\).*\1er" test.txt
五、實際的應用
有了以上的知識儲備,我們就可以用grep來進行一些基本的處理工作了。
1、在/etc/passwd上查找以/sbin/nolog結尾的行,即可以使用以/bin/nologin為結束的位置錨定進行選取
grep "/sbin/nologin$" /etc/passwd
2、在/etc/passwd上查找用戶id和組id在500到1099之間的行
grep "\<1\?[05][0-9][0-9]\>" /etc/passwd
3、查找當前系統上網卡驅動程序的名稱
#顯示pci設備中網卡的信息 #最前面的 “02:01.0” 就是設備在PCI總線上的代號,該代號在整個系統中是唯一的。(因為當前系統上有兩塊網卡,所以有兩條信息) [root@localhost tmp]# lspci | grep "Ethernet" 02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01) 02:05.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01) #sys目錄是內核將設備信息映射出來的一個偽文件系統,所以我們查找到的那一行信息中drivers的子目錄e1000即是網卡設備的驅動名稱 [root@localhost tmp]# find /sys/bus/pci/drivers | grep "02:01.0" /sys/bus/pci/drivers/e1000/0000:02:01.0
其實要做的事也就2步,然后我們可以把這些命令通過管道(|)來把命令連接起來,實現功能。
原創文章,作者:封于修,如若轉載,請注明出處:http://www.www58058.com/4746
才知道封于修不僅武功厲害,文章也相當牛了
@stanley:謝謝stanley大哥,不過我還有好長的路需要努力…呵呵
2、在/etc/passwd上查找用戶id和組id在500到1099之間的行
grep “\” /etc/passwd
這樣取是有問題的,[05]是取0或5,那ID為600-1000間的用戶是取不到的。
中括號只能取一位數,我也不知道怎么取。
@老鼠上了貓:你說的對,我沒有考慮清楚。其實嚴謹的寫grep -E “[5-9][0-9][0-9]|10[0-9][0-9]” /etc/passwd 應該才是對的。
@封于修:你這是用戶IP或組ID為500-1099:
grep -e “[5-9][0-9][0-9]” -e “10[0-9][0-9]” /etc/passwd 這樣也可以
如果需滿足用戶IP和組IP為500-1099的話,只用grep想不出怎么匹配,用awk就比較簡單了:
awk -F: ‘$3>=500 && $4<=1099 {print $0}' /etc/passwd
@老鼠上了貓:條件式的判斷選取用awk是會更好。
grep其實也是可以的,就是會很麻煩。
grep -E “[^:]+:[^:]+:([5-9][0-9][0-9]|10[0-9][0-9]):([5-9][0-9][0-9]|10[0-9][0-9]):.*” /etc/passwd
我試了一下,這樣寫也是可以匹配得到的?;蛟S會有更簡便的寫法,只能等大神解答了。
@封于修:整行匹配肯定沒問題的,這也是一思路,贊!