linux三剑客及正则表达(grep,sed,awk)
首先我們現(xiàn)在知道Linux下一切皆文件,對Linux的操作就是對文件的處理,那么怎么能更好的處理文件呢?這就要用到我們上面的三劍客命令。
??? 在說這三個命令前我們要插入一個小插曲就是“正則表達式”。
目錄
正則表達與三劍客的說明
grep
sed
awk
awk,for,if循環(huán)實現(xiàn)高級搜索
正則表達與三劍客的說明
??? 所謂的正則表達式我個人理解就是正規(guī)的表示方法。他是用簡單的方法來實現(xiàn)強大的功能,所以深受計算機愛好者的使用。
??? 三劍客與正則表達式是什么關系呢?
? 我們可以這樣理解,三劍客就是普通的命令,有的把他們叫做工具,在我看來都一樣。而正則表達式就好比一個模版。三劍客能讀懂這個模版。就這么簡單。
三劍客:
1.grep文本搜索工具(過濾匹配的行)
Linux系統(tǒng)中grep命令是一種強大的文本搜索工具,它能使用正則表達式搜索文本,并把匹配的行打印出來。grep全稱是Global Regular Expression Print,表示全局正則表達式版本,它的使用權限是所有用戶。
2.sed流式編輯器?? 逐行處理
對文檔進行非交互式增刪改查的操作
3.awk精確搜索 (二次處理)
簡單來說,awk就是把文件逐行讀入,以空格為默認分隔符將每行切片,然后可以對切開的部分進行各種處理。相對于grep的查找、匹配和sed的編輯,awk適合對文本進行較復雜的格式處理。
三劍客的對比:
grep:文本過濾器,如果僅僅是過濾文本,可使用grep,其效率要比其他的高很多
sed:Stream EDitor,流編輯器,默認只處理模式空間,不處理原數(shù)據(jù),如果你處理的數(shù)據(jù)是針對行進行處理的,可以使用sed
awk:報告生成器,格式化以后顯示。如果對處理的數(shù)據(jù)需要生成報告之類的信息,或者你處理的數(shù)據(jù)是按列進行處理的,最好使用awk
正則表達式是一個模版,這個模版是由一些普通字符和一些元字符組成。普通字符包括大小寫的字母和數(shù)字,而元字符具有特殊的含義。具體如下
?
?
元字符 補充
grep
grep過濾工具
???????? ---格式:grep 【選項】 “正則表達式“ 文件
egrep 過濾工具
???????? ---格式:egrep 【選項】 “擴展正則表達式“ 文件
舉例子:
head -5 /etc/passwd > user //準備素材 grep ^root user //找以root開頭的行 grep bash$ user //找以bash結尾的行 grep ^$ user //找空行 grep -v ^$ user //顯示除了空行的內(nèi)容grep "[root]" user //找rot任意一個字符 grep "[rot]" user //效果同上 grep "[^rot]" user //顯示r或o或t以外的內(nèi)容 grep "[0123456789]" user //找所有數(shù)字 grep "[0-9]" user //效果同上 grep "[^0-9]" user //顯示數(shù)字以外內(nèi)容 grep "[a-z]" user //找所有小寫字母 grep "[A-Z]" user //找所有大寫字母 grep "[a-Z]" user //找所有字母 grep "[a-Z0-9]" user //找所有字母和數(shù)字 grep "[^a-Z0-9]" user //找特殊符號grep "." user //找任意單個字符,文檔中每個字符都可以理解為任意字符 grep "r..t" user //找rt之間有2個任意字符的行 grep "r.t" user //找rt之間有1個任意字符的行,沒有匹配內(nèi)容,就無輸出 grep "*" user //錯誤用法,*號是匹配前一個字符任意次,不能單獨使用 grep "ro*t" user //找rt,中間的o有沒有都行,有幾次都行 grep ".*" user //找任意,包括空行 .與*的組合在正則中相當于通配符的效果grep "ro\{1,2\}t" user //找rt,中間的o可以有1~2個 grep "ro\{2,6\}t" user //找rt,中間的o可以有2~6個 grep "ro\{2,\}t" user //找rt,中間的o可以有2個以及2個以上 grep "ro\{1,\}t" user //找rt,中間的o可以有1個以及1個以上 grep "ro\{3,\}t" user //找rt,中間的o可以有3個以及3個以上 grep "ro\{2\}t" user //找rt,中間的o必須只有有2個 grep "ro\{1\}t" user //找rt,中間的o必須只有有1個 grep "ro\{3\}t" user //找rt,中間的o必須只有有3個grep "\(0:\)\{2\}" user //找連續(xù)的2個0: 小括號的作用是將字符組合為一個整體以上命令均可以加-E選項并且去掉所有\(zhòng),改成擴展正則的用法,比如 grep "ro\{1,\}t" user可以改成 grep -E "ro{1,}t" user 或者 egrep "ro{1,}t" user grep "ro\{1,\}t" user //使用基本正則找o出現(xiàn)1次以及1次以上 egrep "ro{1,}t" user //使用擴展正則,效果同上,比較精簡 egrep "ro+t" user //使用擴展正則,效果同上,最精簡 grep "ro\{0,1\}t" user //使用基本正則找o出現(xiàn)0~1次 egrep "ro{0,1}t" user //使用擴展正則,效果同上,比較精簡 egrep "ro?t" user //使用擴展正則,效果同上,最精簡 egrep "root|^bin" user //找有root或者以bin開頭的行 #此時的egrep與grep -E相同#單詞邊界 cat aa //素材文件,里面有一些"the" the there the6 the_ 123the egrep "the\b" aa //在aa文件中找the,右邊不允許出現(xiàn)數(shù)字、字母、下劃線 egrep "\bthe\b" aa //找the,兩邊都不允許出現(xiàn)數(shù)字、字母、下劃線?grep正則表達式練習?
先在regular_express.txt寫入內(nèi)容.... 1,過濾包含 the 關鍵字 grep -n 'the' regular_express.txt 2,過濾不包含 the 關鍵字 grep -vn 'the' regular_express.txt 3,過濾不論大小寫 the 關鍵字 grep -in 'the' regular_express.txt 4,過濾 test 或 taste 這兩個單字 grep -n 't[ae]st' regular_express.txt 5,過濾有 oo 的字節(jié) grep -n 'oo' regular_express.txt 6,過濾不想要 oo 前面有 g 的 grep -n '[^g]oo' regular_express.txt 7,過濾 oo 前面不想有小寫字節(jié) grep -n '[^a-z]oo' regular_express.txt. 8,過濾有數(shù)字的那一行 grep -n '[0-9]' regular_express.txt 9,過濾以 the 開頭的 grep -n '^the' regular_express.txt 10,過濾以小寫字母開頭的 grep -n '^[a-z]' regular_express.txt 11,過濾開頭不是英文字母 grep -n '^[^a-zA-Z]' regular_express.txt 12,過濾行尾結束為小數(shù)點.那一行 grep -n '\.$' regular_express.txt 13,過濾空白行 grep -n '^$' regular_express.txt 14,過濾出 g??d 的字串 grep -n 'g..d' regular_express.txt 15,過濾至少兩個 o 以上的字串 grep -n 'ooo*' regular_express.txt 16,過濾 g 開頭和 g 結尾但是兩個 g 之間僅存在至少一個 o grep -n 'goo*g' regular_express.txt 17,過濾兩個 o 的字串 grep -n 'o\{2\}' regular_express.txt 18,過濾 g 后面接 2 到 5 個 o,然后在接一個 g 的字串 grep -n 'go\{2,5\}g' regular_express.txt 19,過濾 g 后面接 2 個以上 o 的 grep -n 'go\{2,\}g' regular_express.txtgrep "bash$" /etc/passwd | sed 's/:.*//' //找到以bash結尾的用戶 再用sed去掉用戶后面:開始的所有內(nèi)容,留下的就是用戶名sed
用法1:前置命令 | sed? [選項]? '條件指令'
用法2:sed? [選項]? '條件指令'? 文件.. ..
選項: -n? 屏蔽默認輸出?? -r? 支持擴展正則? -i 修改源文件
指令: p? 輸出??? d? 刪除??? s替換???? a行下追加??? i行上添加??? c替換整行
以下列子中的文件內(nèi)容可以自己寫入如 :head /etc/passwd > usersed -n 'p' user //輸出所有行 sed -n '1p' user //輸出第1行 sed -n '2p' user //輸出第2行 sed -n '3p' user //輸出第3行 sed -n '2,4p' user //輸出2~4行 sed -n '2p;4p' user //輸出第2行與第4行 sed -n '2,+1p' user //輸出第2行以及后面1行 sed -n '/^root/p' user //輸出以root開頭的行 sed -n '/root/p' user //輸出包含root的行 sed -nr '/^root|^bin/p' user 將以上語句中的p指令改為d指令可以實現(xiàn)對應行的刪除效果 比如sed -n '2p' user 改成 sed '2d' user 是刪除第2行 sed -n '2!p' user //輸出除了第2行的內(nèi)容,加!是取反效果 sed '3,+1!d' user //刪除第3行、第4行以外的行 sed -n '=' user //顯示行號,=號在sed中可以顯示行號 sed -n '$=' user //查看文檔最后一行的行號,相當于查看文檔總行數(shù)sed -i '$d' user //刪除文檔的最后一行并保存sed 's/2017/6666/' test.txt //把所有行的第1個2017替換成6666 sed 's/2017/6666/2' test.txt //把所有行的第2個2017替換成6666 sed '1s/2017/6666/' test.txt //把第1行的第1個2017替換成6666 sed '3s/2017/6666/3' test.txt //把第3行的第3個2017替換成6666 sed '3s/2017//3' test.txt //把第3行的第3個2017替換成空,相當 于刪除 sed '/2024/s/2017/6666/' test.txt //找到有2024的行,將2017替換 成6666嘗試將user文檔中/bin/bash替換成/sbin/sh sed '1s//bin/bash//sbin/sh/' user //直接替換,報錯 sed '1s/\/bin\/bash/\/sbin\/sh/' user //使用轉(zhuǎn)義符號可以 成功,但不方便 sed '1s!/bin/bash!/sbin/sh!' user //最佳方案,更改s的替換符 sed '1s@/bin/bash@/sbin/sh@' user //替換符號可以用所有 數(shù)字鍵上的sed 's/[0-9]//g' nssw.txt sed 's/.//2;s/.$echo abc > abc??????????????????????????? //創(chuàng)建素材 sed -r 's/(a)(b)(c)/\3\2\1/' abc? //替換abc時復制每一個字符,后面替換的內(nèi)容用\數(shù)字粘貼,可以任意調(diào)換位置 echo xyz >> xyz?? //追加內(nèi)容 sed -r 's/(a)(b)(c)/\3\2\1/' abc? //再用之前的方法無法替換第2行 sed -r 's/(.)(.)(.)/\3\2\1/' abc? //將具體字符用 . 替代即可,然后,再將追加abcd時,上述方案失靈 sed -r 's/^(.)(.*)(.)$/\3\2\1/' abc?? //再次升級,分別找到第1個字符和最后1個字符,中間可以是任意 sed -r 's/^(.)(.*)(.)$/\3\2\1/' ?nssw.txt?? //達成需求 //' test?sed -r 's/([A-Z])/(\1)/g' ?nssw.txt? //先找到任意大寫字母,然后保留,最后替換成帶括號的狀態(tài)sed 'a 666' user //所有行的下面追加666 sed '1a 666' user //第1行的下面追加666 sed '/^bin/a 666' user //在以bin開頭的行的下面追加666 sed 'i 666' user //所有行的上面添加666 sed '5i 666' user //第5行的上面添加666 sed '$i 666' user //最后1行的上面添加666 sed 'c 666' user //所有行都替換成666 sed '1c 666' user //替換第1行為666sed -n '/bash$/s/:.*//p' /etc/passwd //用sed找到以bash結尾的用戶 然后去掉用戶后面:開始的所有內(nèi)容,最后加p的作用是僅僅顯示被 替換的行awk
格式1:前置指令 | awk [選項] '[條件]{指令}'?
格式2:awk [選項] '[條件]{指令}' 文件
指令:
print 輸出
選項:
-F 定義分隔符
內(nèi)置變量:
$1第1列? $2第2列? $3 ... $0所有列?? NR行號?? NF列號 awk '{print $1}'? test.txt? //輸出所有行的第1列
使用正則
??~包含?? !~不包含
使用數(shù)字或者字符串?
==? !=?? >=?? >?? <=?? <
邏輯組合?
&&并且?? ||或者
運算
?/?? *?? %?? + ? - .......
awk執(zhí)行額外任務
BEGIN{?? }??? 執(zhí)行1次,讀取文檔之前執(zhí)行
????????逐行任務???? 執(zhí)行n次 ,讀取文檔時執(zhí)行
END{?? }????? 執(zhí)行1次,讀取文檔之后執(zhí)行
簡單的例子:
awk '{print $1}' test.txt //輸出所有行的第1列 awk '{print $3}' test.txt //輸出所有行的第3列 awk '/the/{print $3}' test.txt //輸出有the的行的第3列 awk '/the/{print NR}' test.txt //輸出有the的行的行號 awk '{print NR}' test.txt //輸出所有行的行號 awk '{print NF}' test.txt //輸出所有行的列號 awk '{print $0,NR}' test.txt //輸出所有列然后空格輸出行號 head -5 /etc/passwd > user awk -F: '{print $1}' user //使用-F:修改分隔符為冒號,輸出第1列 awk -F: '{print $1,$7}' user //使用-F:修改分隔符為冒號,輸出第1列空格第7列 awk -F: '{print $1,"的解釋器是",$7}' user //輸出常量加引號ifconfig eth0 | awk '/RX p/{print "服務器eth0網(wǎng)卡的接收流量是"$5"字節(jié)"}' ifconfig eth0 | awk '/TX p/{print "服務器eth0網(wǎng)卡的發(fā)送流量是"$5"字節(jié)"}' df -h | awk '/\/$/{print "根分區(qū)剩余容量是"$4}'awk -F: '$6~/bin/{print}' user //找第6列包含bin的行 awk -F: '$6!~/bin/{print}' user //找第6列不包含bin的行awk -F: 'NR==1{print}' user //輸出第1行 awk -F: 'NR!=3{print}' user //輸出除了第3行以外的行 awk -F: 'NR<4{print}' user //輸出1~3行 awk -F: '$1=="root"{print}' user //輸出第1列等于root的行 awk -F: '$1~/root/{print}' user //輸出第1列包含root的行wk -F: '$3<10&&$7~/bash/' /etc/passwd //輸出第3列(UID)小于10并且 第7列包含bash的行,當給了條件輸出一整行時{print}可以省略不寫 awk -F: 'NR>=2&&NR<=6' /etc/passwd //輸出2~6行 awk -F: '$1~/root/||$3<=5' /etc/passwd //輸出第1列包含root或者UID小 于等于5的行awk 'NR%2==0' user //輸出偶數(shù)行 awk 'BEGIN{ }{ }END{ }' //使用時基本框架 awk 'BEGIN{print "xyz"}{print "xyz"}END{print "xyz"}' user //輸出1 個xyz之后再根據(jù)user文檔的行數(shù)輸出5個xyz,最后再輸出一個xyzawk 'BEGIN{print "User\tUID\tHome"}' //輸出表頭信息 awk -F: '{print $1"\t"$3"\t"$6}' user //輸出內(nèi)容,用戶名,uid,家目錄 awk 'END{print "總計"NR"行"}' user //最后輸出行數(shù)awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1"\t"$3"\t"$6} END{print "總計"NR"行"}' userawk '{print $1}' /var/log/httpd/access_log //可以找出訪問者的ip,但是效果不完美,可以用后面的數(shù)組方式解決awk,for,if循環(huán)實現(xiàn)高級搜索
awk 中使用if單分支,如果滿足條件,就執(zhí)行指令,不滿足就不執(zhí)行任何指令??
if(條件){指令}
awk -F: 'BEGIN{x=0}{if($7~/bash/){x++}}END{print x}'? /etc/passwd? #####統(tǒng)計系統(tǒng)中,有多少用戶使用了bash,首先定義變量x,然后使用if判斷如果每找到一行的$7包含bash,就把x+1,所有逐行任務結束后,最終使用end任務輸出x的值,也就是找系統(tǒng)中使用bash作為解釋器的用戶數(shù)量雙分支,如果滿足條件就執(zhí)行指令,不滿足就執(zhí)行else后面的指令 if(條件){指令}else{指令}
awk -F: 'BEGIN{x=0;y=0}{if($7=="/bin/bash"){x++}else{y++}}END{print x,y}' /etc/passwd //統(tǒng)計系統(tǒng)中使用bash作為解釋器的用戶,和沒有使用bash的用戶數(shù)量,使用if判斷如果每找到一行的$7是/bin/bash,就把x+1,否則y+1,最后使用end輸出x與y的值?多分支 {if (條件){指令}else if (條件){指令}else{指令}}
awk -F: '{if($7=="/bin/bash"){x++}else if($7=="/sbin/nologin"){y++}else{z++}}END{print x,y,z}' /etc/passwd?? //統(tǒng)計系統(tǒng)中使用bash作為解釋器的用戶,使用nologin的用戶,還有其他用戶的數(shù)量,變量如果作為運算使用,并且初始值是0的 ,可以省略定義過程數(shù)組可以用來收集信息
for循環(huán)可以循環(huán)輸出數(shù)組的下標
cat abc.txta[abc]=0 a[abc]++ a[abc]=1 a[xyz]=0 a[xyz]++ a[xyz]=1 a[abc]=1 a[abc]++ a[abc]=2 awk '{a[$1]++}END{print a["abc"],a["xyz"]}' abc.txt //根據(jù)上述結果,得到如果 使用{a[$1]++}走完所有行便可收集到a[xyz]=1和a[abc]=2的結果,所以 在最后使用END任務輸出a[abc]和a[xyz]的值就是 2和 1awk '{a[$1]++}END{for(i in a){print i,a[i]}}' abc.txt //使用for循環(huán),循環(huán)顯示 數(shù)組a的下標,與值,其中for(i in a)里面的i是變量,代表下標,in是語法不 能變,a是數(shù)組名awk '{a[$1]++}END{for(i in a){print i,a[i]}}' /var/log/httpd/access_log //將上述 的abc.txt文件替換成網(wǎng)站的日志,就可以最終用來查看日志得到可以得到 哪個ip來訪以及來訪的次數(shù)awk '{ip[$1]++}END{for(i in ip){print ip[i],i} }' /var/log/httpd/access_log | sort -nr 查看日志中某個ip的出現(xiàn)次數(shù),以及ip,然后按降序排列,出現(xiàn)次數(shù)最大的 顯示在第一行,sort命令可以實現(xiàn)排序效果,-n是以數(shù)字排序,-r是降序awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure //查看哪個ip登錄root賬戶時輸入錯了密碼,先輸出次數(shù),再輸出ip總結
以上是生活随笔為你收集整理的linux三剑客及正则表达(grep,sed,awk)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell的基础学习
- 下一篇: Nginx基本配置