shell命令三劍客之grep命令詳解

正則表達式和grep、vim、awk、sed等的關係:
正則表達式是一種方法,相當於一種工藝,grep等命令相當於是一個具體的加工機器,機器在加工產品的時候,採用這種方法。
三者的效率:grep>sed>awk

1. 通配符(globbing)

常用通配符:

* 代表 匹配0個或者多個字符 
?代表匹配1個字符 
[] :匹配範圍內任意1個字符,例如[az][a-z][a\-z] 
[^…]: 匹配範圍外任意1個字符,表示取反 
{}:組合匹配,touch a{1,3,5} touch b{1..10}  touch {a,b,c}_{1,2,3} 

例:

[0-9] 代表數字
[abcd123]代表取中括號裏的任意一個字符
[a-Z] 代表大小寫字母
[0-Z]代表數字0-9和所有的大小寫字母

正則表達式裏通配符和shell裏面的通配符的區別:

  • shell裏面的通配符:用在bash裏面;
  • 正則裏面的通配符:用在真正的命令裏面。

2. grep

grep全稱通用正則表達式分析程序(global research regular expression and printing)。

其實,grep是一個過濾命令,根據特定的正則表達式來過濾文本里的內容。
grep是根據某個模式進行匹配文件裏的一行一行的數據去處理的,如果有匹配的行,就會將整行輸出到屏幕上。
grep用的時候模式要用雙引號""引起來!!!

用途:使用正則表達式搜索文本,並把匹配的行打印出來

格式:grep [選項] 模式 目標文件

模式其實就是一個公式,裏面有字母+數字+特殊符號,組合成一個正則表達式,表達出某個含義。

常用選項:

-v:invert,反轉查找,輸出與模式不相符的行;
-An:after-context,同時顯示符合條件行的下面n行;
-Bn:before-context,同時顯示符合條件行的上面n行;
-Cn:同時顯示符合條件行的上面n行和下面n行;
-E:extended regular,支持擴展正則表達式;
-o:only-matching,僅顯示匹配的字符串;
-f:根據文件內容進行匹配;
-a:以文本文件方式搜索,不忽略二進制的數據;
-c:計算找到的符合行的次數;
-i:ignore-case忽略大小寫;
-n:line-number,順便輸出行號;
-P  "\t"  --》得到Tab鍵 --》使用perl語言的正則語法,支持\t表示table鍵,\s表示空白。

2.1 linux系統支持的三種形式的grep命令

Linux系統支持三種形式的grep命令,通常將這三種形式的grep命令稱爲grep命令族,這三種形式具體爲:

  1. ls /bin/*grep
  2. fgrep:不支持正則表達式,快速搜索簡單模式,按照字符串的字面意思進行匹配嗎,相當於grep -F
  3. grep:可以使用基本正則表達式搜索
  4. egrep:可以使用基本和擴展正則表達式搜索,相當於grep -E

3. 正則表達式

正則表達式是一個指定文本模式的標準Unix 語法。
使用特殊元字符實現複雜的搜索問題;
元字符(meta characters)是用來闡釋字符表達式意義的字符,簡言之,元字符就是描述字符的字符,它用於對字符表達式的內容、轉換及各種操作信息進行描述。

正則表達式是由一串字符和元字符構成的字符串,簡稱RE(Regular Expression)。

基本正則表達式和Unix兼容;
擴展正則表達式增加了一些新的元字符。

正則表達式由下列元素構成 :

  • 普通字符,a、b 、1、2
  • 通配符,與文件名通配符不是一回事
  • 修飾符:”*” ”?”等
  • 錨點:以什麼開頭、以什麼結尾。

正則裏的通配符:

  1. “.”:表示一定有一個任意字符
例:a…b :代表ab之間有三個字符。
  1. 方括號表達式:一個文字字符域
[abc] :a或者b或者c中的一個。
[^abc] :不是abc其中的一個。
[0-9][a-z][A-Z] : 數字、小寫、大寫。
  1. 域表達式和字符類
    考慮到不同的編碼方案推薦使用字符類方式(此類方法不常用,以被上面②方式代替!)。
[:alnum:]    -字母數字混排 等同於[0-Z]
[:digit:]       -數字  等同於[0-9]
[:lower:]     -小寫字母 等同於[a-z]
[:upper:]    -大寫字母 等同於[A-Z]
[:space:]     -空白字符,空格、TAB、換行符等

通用修飾符(理解爲通配符即可)

  • 問號:表示0個或者1個前面的字符(0或1個)(擴展)
例:ab?c  代表沒有b或者只有一個b,即等同於ac、abc。
  • 星號:表示>=0個前面的字符
例:ab*c 代表沒有b或者多個b,即等同於ac、abc、abbc、abbbc......
  • +:表示1個或者多個前面的字符(>=1)
例:ab+c 代表 一個b或者多個b,即等同於abc、abbc、abbc......
  • {n}:表示n個前面的字符(前面的字符出現了n次)
例:ab{2}c 代表b出現了兩次,即等同於abbc。
  • {n,m}:表示n個到m個前面的字符。
例:ab{2,4}c 代表2個到4個b,即等同於abbc、abbbc、abbbbc。
  • .* :點代表任意一個,星號表示前面的0個或多個,即等同於所有字符。

錨點搜索

  • “^”:表示以什麼開頭行
例 ^aa 代表以aa開頭的行。
  • 美元符:表示以什麼結尾的行
例 bash$代表以bash結尾的行。
  • \<:表示詞首部。作用等同於\b
例 \bwubing 代表以wubing開頭的行。
  • \>:表示詞尾部。作用等同於 \b
例 wubing\b 代表以wubing結尾。 
  • \< abc >:表示abc這個單詞 等價於 \babc\b
例 \<wubing\> 代表wubing這個單詞。

grep在界定單詞的時候,默認使用的分隔符是空白。

3.1 擴展正則表達式

egrep、awk和Perl等Linux工具還支持正則表達式擴展出來的一些元字符,這些元字符如下表所示:

  • ?:匹配0個或1個在其之前的那個普通字符
  • +:匹配1個或多個在其之前的那個普通字符
  • ( ):表示一個字符集合
  • | :表示’或’,匹配一組可選的字符

正則表達式分組
①“?”、”*”、”+”默認只能修飾前面一個字符
②利用圓括號( )可以實現多個字符分組。

例 f(oo)* :因爲oo括起來了,所以把oo看成"一個字符",即f、foo、foooo......

③在圓括號中利用”|”實現或者的功能

echo foooeee | egrep --color "(oo|ee){2}"
echo foooeee | egrep --color "(oo|ee){1}"

轉義元字符

egrep ‘cat.' /etc/aa
egrep ‘cat\.' /etc/aa

正則表達式與通配符匹配的區別:

  • 正則表達式只在少數搜索和替換文本命令中使用;
  • 文件名匹配在bash中匹配文件名;
  • 都使用”*”、”?”但意義不一樣;
  • 正則表達式元字符要放在引號內,避免bash Shell解釋。

4. IP的正則

4.1 ip地址的類別

簡單來講分爲三類:

  • A類網絡的IP地址範圍爲:1.0.0.1-126.255.255.254;
  • B類網絡的IP地址範圍爲:128.1.0.1-191.255.255.254;
  • C類網絡的IP地址範圍爲:192.0.1.1-223.255.255.254

4.2 ip地址的正則

寫ip地址正則時的方法:需要按個位(1位)、十位(2位)、百位(3位)
顯示文件中的所有A類地址:(1-126)

"\b([1-9]|[1-9][0-9]|1[01][0-9]|12[0-6])(\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ){3}\b"   

解析:
先寫的個位,十位,百位先寫的100-119,再120-126;
0-255,先0-9,再10-99,100-199,200-249,最後250-255

顯示文件中的所有B類地址:(128-191)

 "\b(12[89]|1[3-8][0-9]|19[01])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]) ){3}\b"

顯示文件中的所有C類地址:(192-223)

"\b(19[2-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]) ) {3}\b"

匹配email地址:

egrep "[0-Z._]+@[0-Z]+\.[a-Z]+"

匹配HTTP URL:

egrep "^http://([0-Z]+\.){2}[a-Z]{2,3}"
egrep --color "http://(.*\..*){2}" --》網址至少有兩個點!(適用所有網址)

5. shell中的特殊字符

  • :冒號
    內置的空命令,返回值爲0–》while :
  • ;分號
    連續運行命令
  • | 管道
    前面命令的標準輸出作爲後面命令的標準輸入
    正則中表示或者
  • &
    將命令放到後臺執行
    表示標準輸出和標準錯誤輸出
  • &&
    前面命令執行成功才執行後面的命令
  • ||
    前面命令執行不成功才執行後面的命令
  • 井號
    表示註釋
  • ? 問號
    通配符中表示任意1個字符
    正則表達式中表示0個或者1個前面的字符
  • 星號
    通配符中表示0個到多個任意字符
    正則表達式中表示0個或者多個前面的字符
    算術運算中的乘法
  • !驚歎號
    將命令或者條件表達式的返回值取反
    執行歷史命令
    vi或者ftp中執行外部shell命令
    間接應用變量 --》${!b}
  • $ 美元符號
    取變量的值
    正則表達式表示行尾
  • \ 反斜槓
    單字符轉義
  • 大於號
    輸出重定向
    條件測試中的大於號
  • 小於號
    輸入重定向
    條件測試中的小於號
  • = 等號
    變量賦值
    條件測試中的等號
  • 加號
    算術運算中的加號
    正則表達式中1個或多個前面的字符
  • >>
    輸出重定向追加
    <<
    here document
  • - 減號
    算術運算中的減號
    命令的選項
    上一次工作目錄
    通配符和正則表達式中表示範圍[a-z]
    tar -cvf - /home | tar -xvf - 表示輸出流或輸入流
  • ’ ’ 單引號
    解決變量賦值空格的問題
    阻止shell替換
  • " " 雙引號
    解決變量賦值空格的問題
    阻止shell部分字符替換,對$、!等無效
  • `` 反引號
    命令行替換
  • % 百分號
    算術運算中的模運算
    vi中替換操作中表示所有行
  • () 單圓括號
    子shell中執行命令,會繼承父shell的變量
    括起數組元素
  • (()) 雙圓括號
    算術運算
    整數比較測試
  • [] 單方括號
    通配符和正則中表示匹配括號中的任意一個字符
    條件測試表達式
    數組中下標括號
  • [[]] 雙方括號
    字符串比較測試 --》不能比較小數!比較小數要用bc計算機–》echo “4.5>5.5”|bc ,返回值爲0,假的
  • . 句點號
    正則中表示任意1個字符
    當前shell執行腳本命令
    表示當前目錄
  • {} 大括號
    通配符擴展 abc{1,2,3}
    正則表達式中表示範圍
    匿名函數{cmd1;cmd2;cmd3} &> /dev/null
    括起變量名${abc}a
  • / 正斜槓
    算術運算中的除法
    根目錄或路徑分割符
  • ^
    在[^abc]通配符中表示取反
    在正則表達式中表示以什麼開頭

6. 練習

1.新建/lianxi目錄,複製/etc/passwd到當前目錄下。
2.查找出當前passwd文件中以ftp開頭或者mail開頭的行,在屏幕輸出。
3.查找出當前passwd文件中首行不是以r、m、f開頭的行,在屏幕輸出。
4.查找出當前passwd文件中以bash結尾的行。
5.查找出/etc/login.defs文件中的有效行(不顯示空行和註釋行)。
6.查找出/var/log/messages文檔中有16個字母的單詞。
7.查找/etc/passwd文件裏用戶名包含liu同時使用bash的用戶。
8.查找/etc/ssh/sshd_config文件裏的有效行。
9.查找/etc/ssh/sshd_config文件裏的包含連續2個數字的行。
10.查找出包含特殊字符的行。
11.查找出不包含數字的行。
12.查找出/var/log/messages裏的ip地址出來。
13.寫一個正則來表示出下面的網址,例如:

http://www.baidu.com
http://www.sina.com
http://www.163.com
http://www.12306.cn
http://www.qillu.edu

14.寫一個表示郵箱的正則,例如:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

15.C類ip地址的正則表達式
section1:範圍在192-223之間
section2和section3和section4範圍:0-255之間
例如:193.168.23.1
16.監控/var/log/secure文件,統計出ssh錯誤連接本機次數超過十次的ip地址,拒絕這個ip地址再ssh連接過來(將這個ip地址寫入到/etc/hosts.deny黑名單,/etc/hosts.allow是白名單)。

答案:
1.新建/lianxi目錄,複製/etc/passwd到當前目錄下。

mkdir /lianxi
cd /lianxi 
cp /etc/passwd .

2.查找出當前passwd文件中以ftp開頭或者mail開頭的行,在屏幕輸出。

cat passwd|grep "^ftp|^mail"

3.查找出當前passwd文件中首行不是以r、m、f開頭的行,在屏幕輸出。

cat passwd|grep -v "^r|^m|^f"

4.查找出當前passwd文件中以bash結尾的行。

cat passwd|grep "bash$"

5.查找出/etc/login.defs文件中的有效行(不顯示空行和註釋行)。

cat /etc/login.defs|egrep -v "^$|^#"

6.查找出/var/log/messages文檔中有16個字母的單詞。

cat /var/log/messages|egrep "\<[0-Z]{16}\>"

7.查找/etc/passwd文件裏用戶名包含liu同時使用bash的用戶。

cat passwd|egrep "^[0-Z]*liu[0-Z]*" | egrep "bash" 

cat /etc/passwd|egrep "^.*liu.*:x:"|egrep "bash"

cat passwd|egrep "^[0-Z_]*liu.*bash$"

8.查找/etc/ssh/sshd_config文件裏的有效行。

cat /etc/ssh/sshd_config|egrep -v "^$|^#"

9.查找/etc/ssh/sshd_config文件裏的包含連續2個數字的行。

cat /etc/ssh/sshd_config|egrep "\b[0-9]{2}\b"

10.查找出包含特殊字符的行。

cat /etc/ssh/sshd_config|egrep "[^0-Z]" --》包含特殊字符(^在[]裏面,表示取反)

11.查找出不包含數字的行。

cat /etc/passwd|grep -v ".*[0-9].*"

12.查找出/var/log/messages裏的ip地址出來。

cat /var/log/messages | egrep "\b([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ){3}\b"

13.寫一個正則來表示出下面的網址,例如:
http://www.baidu.com
http://www.sina.com
http://www.163.com
http://www.12306.cn
http://www.qillu.edu

[root@liupeng lianxi]# cat dizhi.txt 
http://www.baidu.com
http://www.sina.com
http://www.163.com
http://www.12306.cn
http://www.qillu.edu
[root@liupeng lianxi]# cat dizhi.txt|egrep --color "http://(.*\..*){2}"
http://www.baidu.com
http://www.sina.com
http://www.163.com
http://www.12306.cn
http://www.qillu.edu
[root@liupeng lianxi]# 

14.寫一個表示郵箱的正則,例如:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

PS:用戶名最大16位。

[root@liupeng lianxi]# cat youxiang.txt 
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[root@liupeng lianxi]# cat youxiang.txt|egrep "\b[0-Z._]{1,16}+@[0-Z]+\.[a-Z]+\b"
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[root@liupeng lianxi]# 

15.C類ip地址的正則表達式
section1:範圍在192-223之間
section2和section3和section4範圍:0-255之間
例如:193.168.23.1

[root@liupeng lianxi]# cat ipip.txt 
193.168.23.1
10.10.10.1
192.168.12.12
123.123.123.123
[root@liupeng lianxi]# cat ipip.txt|egrep "\b(19[2-9]|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}\b"
193.168.23.1
192.168.12.12
[root@liupeng lianxi]# 

16.監控/var/log/secure文件,統計出ssh錯誤連接本機次數超過十次的ip地址,拒絕這個ip地址再ssh連接過來(將這個ip地址寫入到/etc/hosts.deny黑名單,/etc/hosts.allow是白名單)。

#!/bin/bash
while true
do
        cat secure|egrep "Failed passwd"|egrep -o "\b192(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}\b"|sort|uniq -c|sort -nr >secure.txt
        deny=$(cat /etc/hosts.deny|egrep "^sshd:192(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"|awk -F: '{print $2}')
        echo $deny >deny_ip.txt
        cat secure.txt|while read times IP
        do
                if (( $times>=2 ))
                then
                        if ! grep $IP deny_ip.txt &>/dev/null
                        then
                                echo "sshd:$IP" >>/etc/hosts.deny&&echo "$IP has been written to /etc/hosts.deny"
                        fi
                fi
        done
sleep 1
done

在這裏插入圖片描述

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