linux學習筆記: grep命令,正則表達式

linux學習筆記:grep命令,正則表達式

linux運維筆記


  • 簡介 
    grep命令是一個最初用于Unix操作系統的命令行工具,在給出文件列表或者標準輸入之后,grep會對匹配一個或者多個正則表達式的文本進行搜索,并且只輸出匹配或者不匹配的行或者文本。(參見維基百科) 
     
    正則表達式是計算機科學的一個概念,正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。在很多文本編輯器里面,正則表達式通常被用來檢索、替換那些匹配某個模式的文本。(參見維基百科)


  • grep, 正則表達式的作用 
    在生產環境或者實驗環境中,我們經常會對linux操作系統下的日志以及配置文件進行文本處理,從中截獲、修改我們感興趣的內容,進行分析和處理。通過grep命令,結合正則表達式,可以靈活地完成各種文本處理,從而達到事半功倍的目的。 
  • grep命令的常用選項 
    完全詳細的grep命令的選項以及作用,可以參照man手冊,或者google,這里僅總結一些常用的選項:
命令選項 解釋
-v 顯示不被pattern匹配到的行
-i 忽略字母的大小寫
-n 顯示匹配的行號
-c 統計匹配的行數
-o 僅顯示匹配到的字符串
-q 靜默模式,不輸出任何信息
-A <num> 不僅輸出匹配的行,同時輸出該匹配行后面的num行
-B <num> 不僅輸出匹配的行,同時輸出該匹配行之前的num行
-C <num> 不僅輸出匹配的行,同時輸出該行前后各num行
-e 實現多個選項之間的邏輯or關系
-w 匹配整個單詞
-E 使用egrep擴展模式進行正則匹配
-F 相當于fgrep(fast grep),并不支持正則表達式

$ cat /etc/nsswitch.conf | grep -v "^#" | grep -v "^$" #刪空行和注釋行
passwd:     files sss
shadow:     files sss
group:      files sss
......
......
$ echo "HELLO" | grep -i "hello" #不區分大小寫的匹配
HELLO
$ cat /etc/passwd | grep -c bash #統計使用bash用戶的數量
3
......
......
$ cat /etc/passwd | grep -n bash #匹配使用bash用戶的行并添加行號
1:root:x:0:0:root:/root:/bin/bash
23:user1:x:1000:1000::/home/user1:/bin/bash
24:guest:x:1002:1002::/home/guest:/bin/bash
......
......

$ cat /etc/passwd | grep -o bash #僅僅顯示匹配到的字符串本身
bash
bash
bash
......
......
$ cat /etc/passwd | grep -q bash; echo $? #靜默模式
0
$ cat /etc/passwd | grep -q abcdefg; echo $? #靜默模式   
1
......
......
$ cat grep -A3 -B3 "^\bshutdown\b" /etc/passwd #shutdown前后3行
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
$ cat grep -C3 "^\bshutdown\b" /etc/passwd #同上
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
......
......
$ grep -e "root"  -e "lp"  -e "ftp" /etc/passwd #邏輯或
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
......
......
$ cat 1.txt 
/bin/bash
bash/bin
bash
/bin/bash/bin
binbashbin
$ cat 1.txt | grep -w bash #-w選項無法匹配binbashbin中的bash
/bin/bash
bash/bin
bash
/bin/bash/bin
......
......

  • linux,grep,與正則表達式 
    正則表達式的實現(參見:正則引擎)有很多種,在linux操作系統里面,默認引擎為PCRE(Perl Compatible Regular Expressions),依照維基百科,PCRE庫、Perl語言、PHP語言、Python語言,對正則表達式的支持是最好的。linux系統的程序,如grep, sed, awk, vim, less, nginx, varnish等,都支持正則表達式。 
     
    針對grep程序,支持基本的正則表達式(BRE)以及擴展的正則表達式(ERE),可以通過grep -E命令或者egrep命令,使用擴展的正則表達式。 
     
    更多的正則表達式的內容,可以參見linux下面的man手冊: man 7 regex 

  • 正則表達式的元字符 
    在正則表達式中,具有特殊意義的字符集,稱為元字符。常用的元字符如下表所示:

元字符 含義
^ 行首錨定
$ 行尾錨定
. 匹配任意單個字符
[] []內任意單一字符
[^] 除[]內任意單一字符
* *前面的字符重復0次或者多次
\+ \+前面字符重復1次或者多次
\? ?前面的字符重復0次或者1次
\ 轉義符
\{n\} 前面字符重復n次
\{n,\} 前面字符重復n次(包括n次)以上
\{m,n\} 前面的字符重復m次(包括m次)和n次(包括n次)之間
[:alnum:] 字母和數字
[:alpha:] 代表任何英文大小寫字母
[:lower:] 小寫字母
[:upper:] 大寫字母
[:blank:] 水平空白符
[:space:] 垂直空白字符
[:cntrl:] 不可打印的控制字符(退格、刪除、警鈴……)
[:digit:] 十進制數字
[:graph:] 可打印的空白字符
[:pnuct:] 標點符號
[:xdigit:] 十六進制數字

示例如下所示:

1. 顯示/proc/meminfo文件中以大s或者小s開頭的行:
$ cat /proc/meminfo | grep -i "^s.*$"
$ cat /proc/meminfo | grep "^[sS].*$"

2.顯示CentOS7上面所有系統用戶的用戶名和UID:
$ cat /proc/meminfo | grep -v "root" | grep -v "\b[0-9]\{4,\}\b"

3.取出/etc/rc.d/init.d/functions的基名
 echo "/etc/rc.d/init.d/functions" | egrep -o "/[[:alpha:]]+$" |  \
 egrep -o "[[:alpha:]]+"

4.使用egrep取出上面路徑的目錄名 #貪婪匹配
echo "/etc/rc.d/init.d/functions" | egrep -o "/.*/"

5.找出/etc/rc.d/init.d/functions文件中行首為某單詞(包括下劃線)后面跟一個小括號的行
$ cat /etc/rc.d/init.d/functions  | egrep "^[_[:alpha:]]+\(\)"
  • 正則表達式的分組 
    將一個或者多個字符捆綁在一起,當做一個整體進行處理,例如:\(root\)\+ 
    分組括號中的匹配模式匹配到的內容會被正則引擎記錄于內部變量當中,這些變量的分組的命名方式為\1, \2, \3,…… 
    當然,我們也可以自己定義分組名稱。利用(?<Word>\w+),這樣就會將\w+匹配到的內容賦值給分組Word??梢酝ㄟ^\k<Word>引用這個分組1。 
    分組的語法格式如下表所示:
表達式 解釋
(exp) 匹配exp, 捕獲文本到自動命名的組里面: \1, \2, …
(?<name>exp) 匹配exp,捕獲文本到名稱為name的組里面
(?:exp) 匹配exp,不捕獲匹配的文本
(?=exp) 匹配exp前面的位置,但是并不包括exp本身
(?<=exp) 匹配exp后面的位置,但是并不包括exp本身
(?!exp) 匹配后面不是exp的位置,不包括那個不是exp的模式
(?<!exp) 匹配前面不是exp的位置,不包括那個不是exp的模式

其中的(?=exp)被稱為零寬先行斷言,其中的(?<=exp)被成為零寬后行斷言。 

使用案例如下所示:

1. 找出/etc/passwd下面用戶名同shell名的行
$ cat /etc/passwd | grep -P "^\b(\w+):\b.*\1$"
......
......
2.匹配開頭是/bin/的內容,但是并不包括/bin/本身
[root@centos7-front1 ~]# cat -n 1.txt 
     1  /bin/bash
     2  /bin/bash/bin/
     3  <bash>
     4  <bash
[root@centos7-front1 ~]# cat 1.txt | grep -noP "(?<=/bin).*"
1:/bash
2:/bash/bin/
......
......
3.匹配結尾為/bin/的內容,但是并不包括/bin/本身
[root@centos7-front1 ~]# cat -n 1.txt 
     1  /bin/bash
     2  /bin/bash/bin/
     3  <bash>
     4  <bash
[root@centos7-front1 ~]# cat 1.txt | grep -noP "^.*(?=/bin/$)"
2:/bin/bash
......
......
3.匹配由兩個尖括號包裹的內容,但是并不包括兩個尖括號本身
[root@centos7-front1 ~]# cat -n 1.txt 
     1  /bin/bash
     2  /bin/bash/bin/
     3  <bash>
     4  <bash
[root@centos7-front1 ~]# cat 1.txt | grep -noP "(?<=<).*(?=>)"
3:bash
......
......
4.匹配簡單html標簽
$ echo "<font color=#ff0000>color font</font>" \
 | grep -oP "(?<=>).*(?=</font>)"
color font
......
......
5.匹配出/etc/passwd文件中用戶id和數組id相同的用戶
$ grep -P ".*\b:(?<UID>\w+):\b\k<UID>.*$" /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
nobody:x:99:99:Nobody:/:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
user1:x:1000:1000::/home/user1:/bin/bash
guest:x:1002:1002::/home/guest:/bin/bash
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
  • 貪婪模式與懶惰模式 
    當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符。以這個表達式為例:a.*b,它將會匹配最長的以a開始,以b結束的字符串。如果用它來搜索aabab的話,它會匹配整個字符串aabab。這被稱為貪婪匹配 
     
    有時,我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉化為懶惰匹配模式,只要在它后面加上一個問號?。這樣.*?就意味著匹配任意數量的重復,但是在能使整個匹配成功的前提下使用最少的重復。 
     
    懶惰限定符如下表所示:
限定符 說明
*? 重復任意次,但是盡可能少地重復
+? 重復1次或者更多次,但是盡可能少地重復
?? 重復0次或者1次,但是盡可能少地重復
{n,m}? 重復n到m次,但是盡可能少地重復
{n,}? 重復n次,但是盡可能少地重復

使用示例如下所示:

[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.*b"
aababab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.*?b"
aab
ab
ab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.+?b"
aab
abab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.??b"
aab
ab
ab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.{0,1}?b"
aab
ab
ab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.{1,}?b" 
aab
abab

注釋:


  1. 使用分組的時候,最好使用grep -P命令,使用Perl正則擴展。 ?

原創文章,作者:jiangche00,如若轉載,請注明出處:http://www.www58058.com/72707

(0)
jiangche00jiangche00
上一篇 2017-04-06
下一篇 2017-04-07

相關推薦

  • shell腳本編程練習

    1、寫一個腳本,使用ping命令探測172.16.250.1-172.16.250.254之間的所有主機的在線狀態 在線的主機使用綠色顯示 不在線的主使用紅色顯示 #!/bin/bash # for i in {1..254};do if ping -c 6 -w 1 192.168.1.$i &> /dev/null;then echo -e…

    2017-11-15
  • 【譯文】如何正確設定MySQL程序的選項

    MySQL手冊文檔版本:5.6  章節:4.2 Using MySQL Programs  略去了部分windows下使用mysql的相關的說明 譯者:古二娃 時間:2015-03-15 章節目錄: 4.2 Using MySQL Programs 4.2.1 Invoking MySQL Programs …

    Linux干貨 2015-03-10
  • 第十三周作業

    1、建立samba共享,共享目錄為/data,要求:(描述完整的過程)   1)共享名為shared,工作組為magedu;   2)添加組develop,添加用戶gentoo,centos和ubuntu,其中gentoo和centos以develop為附加組,ubuntu不屬于develop組;密碼均為用戶名;  3)添加sa…

    Linux干貨 2017-04-04
  • systemd

    systemd的新特性(centos 7) 系統引導時實現服務并行啟動 按需激活進程,在此之前可以讓進程處于半活動狀態 系統狀態快照:能夠自我保存當前系統上沒一個用戶空間的進程運行狀態快照,將來可以迅速恢復到某一種狀態,因此用戶空間有了時間機器??梢曰貪L到過去某一時刻的狀態 內在的基于依賴關系定義的服務控制邏輯 對與systemd來講,引入了一個新的核心概念…

    Linux干貨 2016-09-23
  • vim shell 練習作業題

    vim練習題 1. 復制/etc/profile至/tmp/目錄,用查找替換命令刪除/tmp/profile文件中的行首的空白字符   :%s/^[[:blank:]]\+//g 【注意要把/etc/profile復制到/tmp下,cp  /etc/profile  /tmp(盡量不要修改原文件)】 2. 復制/etc/rc.d…

    2017-08-07

評論列表(1條)

  • renjin
    renjin 2017-04-12 11:17

    詳細的介紹了grep 以及正則表達式,內容寫的很不錯,版本也非常好,贊!

欧美性久久久久