2015年12月25日 16:28:50 張小凡vip 閱讀數 5404更多html
所屬專欄: linux基礎與shell編程linux
版權聲明:本文爲博主原創文章,未經博主容許不得轉載。 https://blog.csdn.net/q383965374/article/details/50394765正則表達式
咱們前面已經學習過 linux的性能查詢(top),以及網絡端口查詢(netstat)命令等等。shell
怎麼讓咱們查詢到的信息按 咱們須要的格式 顯示生成。express
就是咱們本章 須要 學習練習的。編程
主要是grep,sed,awk3個命令的運用。數組
grep主要負責搜索緩存
sed主要負責處理行bash
awk主要複雜處理列網絡
咱們在下一章的內容再來學習實例,若是用這幾個命令來進行性能監控等。
grep命令能夠指定文件中搜索特定的內容,並將含有這些內容的行標準輸出。
grep全稱是Global Regular Expression Print,表示全局正則表達式版本,它的使用權限是全部用戶。
[options]主要參數:
-c:只輸出匹配行的計數。
-I:不區分大小寫(只適用於單字符)。
-h:查詢多文件時不顯示文件名。
-l:查詢多文件時只輸出包含匹配字符的文件名。
-n:顯示匹配行及行號。
-s:不顯示不存在或無匹配文本的錯誤信息。
-v:顯示不包含匹配文本的全部行。
pattern正則表達式主要參數:
\:忽略正則表達式中特殊字符的原有含義。
^:匹配正則表達式的開始行。
$: 匹配正則表達式的結束行。
\:到匹配正則表達式的行結束。
[ ]:單個字符,如[A]即A符合要求。
[ - ]:範圍,如[A-Z],即A、B、C一直到Z都符合要求。
。:全部的單個字符。
* :有字符,長度能夠爲0。
.... 保存已匹配的字符
正則表達式是Linux/Unix系統中很是重要的概念。正則表達式(也稱爲「regex」或「regexp」)是一個能夠描述一類字符串的模式(Pattern)。
若是一個字符串能夠用某個正則表達式來描述,咱們就說這個字符和該正則表達式匹配(Match)。
這和DOS中用戶可使用通配符「*」表明任意字符相似。
在Linux系統上,正則表達式一般被用來查找文本的模式,以及對文本執行「搜索-替換」操做和其它功能。
$ ls -l | grep '^a'
經過管道過濾ls -l輸出的內容,只顯示以a開頭的行。
$ grep 'test' d*
顯示全部以d開頭的文件中包含test的行。
$ grep 'test' aa bb cc
顯示在aa,bb,cc文件中匹配test的行。
$ grep '[a-z]\{5\}' aa
顯示aa文件中全部包含每一個字符串有5個連續小寫字符的字符串的行。
$ grep 'w\(es\)t.*\1' aa
若是west被匹配,則es就被存儲到內存中,並標記爲1,而後搜索任意個字符(.*),這些字符後面緊跟着另一個\1 ,\1也就是es,由於前面把es存儲到了內存並默認標記爲1了,找到就顯示該行。若是用egrep或grep -E,就不用"\"號進行轉義,直接寫成'w(es)t.*\1'就能夠了。
sed 經常用於一整個行的處理。sed是一種在線編輯器,它一次處理一行內容。處理時,把當前處理的行存儲在臨時緩衝區中,稱爲「模式空間」(pattern space),接着用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往屏幕。接着處理下一行,這樣不斷重複,直到文件末尾。文件內容並無 改變,除非你使用重定向存儲輸出。Sed主要用來自動編輯一個或多個文件;簡化對文件的反覆操做;編寫轉換程序等。
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
-n :使用安靜(silent)模式。在通常 sed 的用法中,全部來自 STDIN 的數據通常都會被列出到終端上。但若是加上 -n 參數後,則只有通過sed 特殊處理的那一行(或者動做)纔會被列出來。
-e :直接在命令列模式上進行 sed 的動做編輯;
-f :直接將 sed 的動做寫在一個文件內, -f filename 則能夠運行 filename 內的 sed 動做;
-r :sed 的動做支持的是延伸型正規表示法的語法。(默認是基礎正規表示法語法)
-i :直接修改讀取的文件內容,而不是輸出到終端。
a :新增, a 的後面能夠接字串,而這些字串會在新的一行出現(目前的下一行)~
c :取代, c 的後面能夠接字串,這些字串能夠取代 n1,n2 之間的行!
d :刪除,由於是刪除啊,因此 d 後面一般不接任何咚咚;
i :插入, i 的後面能夠接字串,而這些字串會在新的一行出現(目前的上一行);
p :列印,亦即將某個選擇的數據印出。一般 p 會與參數 sed -n 一塊兒運行~
s :取代,能夠直接進行取代的工做哩!一般這個 s 的動做能夠搭配正規表示法!例如 1,20s/old/new/g 就是啦!
^ 行首定位符
/^my/ 匹配全部以my開頭的行
$ 行尾定位符
/my$/ 匹配全部以my結尾的行
. 匹配除換行符之外的單個字符
/m..y/ 匹配包含字母m,後跟兩個任意字符,再跟字母y的行
* 匹配零個或多個前導字符
/my*/ 匹配包含字母m,後跟零個或多個y字母的行
[] 匹配指定字符組內的任一字符
/[Mm]y/ 匹配包含My或my的行
[^] 匹配不在指定字符組內的任一字符
/[^Mm]y/ 匹配包含y,但y以前的那個字符不是M或m的行
.... 保存已匹配的字符
1,20s/youyouself/\1r/ 標記元字符之間的模式,並將其保存爲標籤1,以後可使用\1來引用它。最多能夠定義9個標籤,從左邊開始編號,最左邊的是第一個。此例中,對第1到第20行進行處理,you被保存爲標籤1,若是發現youself,則替換爲your。
& 保存查找串以便在替換串中引用
s/my/**&**/ 符號&表明查找串。my將被替換爲**my**
\< 詞首定位符
/\<my/ 匹配包含以my開頭的單詞的行
\> 詞尾定位符
/my\>/ 匹配包含以my結尾的單詞的行
x\{m\} 連續m個x
/9\{5\}/ 匹配包含連續5個9的行
x\{m,\} 至少m個x
/9\{5,\}/ 匹配包含至少連續5個9的行
x\{m,n\} 至少m個,但不超過n個
/9\{5,7\}/ 匹配包含連續5到7個9的行
定址用於決定對哪些行進行編輯。地址的形式能夠是數字、正則表達式、或兩者的結合。若是沒有指定地址,sed將處理輸入文件的全部行。
地址是一個數字,則表示行號;是「$"符號,則表示最後一行。
$ sed '2d' example
刪除example文件的第二行。
$ sed '2,$d' example
刪除example文件的第二行到末尾全部行。
$ sed '$d' example
刪除example文件的最後一行。
$ sed '/test/'d example
刪除example文件全部包含test的行。
$ sed 's/test/mytest/g' example
在整行範圍內把test替換爲mytest。若是沒有g標記,則只有每行第一個匹配的test被替換成mytest。
$ sed -n 's/^test/mytest/p' example
(-n)選項和p標誌一塊兒使用表示只打印那些發生替換的行。也就是說,若是某一行開頭的test被替換成mytest,就打印它。
$ sed 's/^192.168.0.1/&localhost/' example
&;符號表示替換換字符串中被找到的部份。全部以192.168.0.1開頭的行都會被替換成它自已加localhost,變成192.168.0.1localhost。
$ sed -n 's/\(love\)able/\1rs/p' example
love被標記爲1,全部loveable會被替換成lovers,並且替換的行會被打印出來。
$ sed 's#10#100#g' example
不論什麼字符,緊跟着s命令的都被認爲是新的分隔符,因此,「#」在這裏是分隔符,代替了默認的「/」分隔符。表示把全部10替換成100。
$ sed -n '/test/,/check/p' example
全部在模板test和check所肯定的範圍內的行都被打印。
$ sed -n '5,/^test/p' example
打印從第五行開始到第一個包含以test開始的行之間的全部行。
$ sed '/test/,/check/s/$/sed test/' example
對於模板test和west之間的行,每行的末尾用字符串sed test替換。
$ sed -e '1,5d' -e 's/test/check/' example
(-e)選項容許在同一行裏執行多條命令。如例子所示,第一條命令刪除1至5行,第二條命令用check替換test。命令的執行順序對結果有影響。若是兩個命令都是替換命令,那麼第一個替換命令將影響第二個替換命令的結果。
$ sed --expression='s/test/check/' --expression='/love/d' example
一個比-e更好的命令是--expression。它能給sed表達式賦值。
$ sed '/test/r file' example
file裏的內容被讀進來,顯示在與test匹配的行後面,若是匹配多行,則file的內容將顯示在全部匹配行的下面。
$ sed -n '/test/w file' example
在example中全部包含test的行都被寫入file裏。
$ sed '/^test/a\\this is a test line' example
在example文件中'this is a test line'被追加到以test開頭的行後面,sed要求命令a後面有一個反斜槓。
$ sed '/test/i\\new line-------------------------' example
若是test被匹配,則把反斜槓後面的文本插入到匹配行的前面。
$ sed '/test/{ n; s/aa/bb/; }' example
若是test被匹配,則移動到匹配行的下一行,替換這一行的aa,變爲bb,並打印該行,而後繼續。
$ sed '1,10y/abcde/ABCDE/' example
把1--10行內全部abcde轉變爲大寫,注意,正則表達式元字符不能使用這個命令。
$ sed '10q' example
打印完第10行後,退出sed。
$ sed -e '/test/h' -e '$G example
在sed處理文件的時候,每一行都被保存在一個叫模式空間的臨時緩衝區中,除非行被刪除或者輸出被取消,不然全部被處理的行都將打印在屏幕上。接着模式空間被清空,並存入新的一行等待處理。在這個例子裏,匹配test的行被找到後,將存入模式空間,h命令將其複製並存入一個稱爲保持緩存區的特殊緩衝區內。第二條語句的意思是,當到達最後一行後,G命令取出保持緩衝區的行,而後把它放回模式空間中,且追加到如今已經存在於模式空間中的行的末尾。在這個例子中就是追加到最後一行。簡單來講,任何包含test的行都被複制並追加到該文件的末尾。
$ sed -e '/test/h' -e '/check/x' example
互換模式空間和保持緩衝區的內容。也就是把包含test與check的行互換。
awk 比較傾向於一行當中分紅數個『欄位』(或者稱爲一個域,也就是一列)來處理。awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤其強大。簡單來講awk就是把文件逐行的讀入,以空格爲默認分隔符將每行切片,切開的部分再進行各類分析處理。
awk有3個不一樣版本: awk、nawk和gawk,未做特別說明,通常指gawk,gawk 是 AWK 的 GNU 版本。
awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有本身的語言: AWK 程序設計語言 , 三位建立者已將它正式定義爲「樣式掃描和處理語言」。它容許您建立簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其餘的功能。
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。
在awk中,文件的每一行中,由域分隔符分開的每一項稱爲一個域。一般,在不指名-F域分隔符的狀況下,默認的域分隔符是空格。
awk的命令很是多,由於它甚至能夠算是一個編程語言。咱們這裏就不詳細講述了。後面的實例學習中會了解到一部分經常使用的命令。
這裏大概給出awk中的一些學習目錄以下:
awk中同時提供了print和printf兩種打印輸出的函數。
其中print函數的參數能夠是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。若是沒有逗號,參數就串聯在一塊兒而沒法區分。這裏,逗號的做用與輸出文件的分隔符的做用是同樣的,只是後者是空格而已。
printf函數,其用法和c語言中printf基本類似,能夠格式化字符串,輸出複雜時,printf更加好用,代碼更易懂。
變量描述
$n 當前記錄的第n個字段,字段間由FS分隔。
$0 完整的輸入記錄。
ARGC 命令行參數的數目。
ARGIND 命令行中當前文件的位置(從0開始算)。
ARGV 包含命令行參數的數組。
CONVFMT 數字轉換格式(默認值爲%.6g)
ENVIRON 環境變量關聯數組。
ERRNO 最後一個系統錯誤的描述。
FIELDWIDTHS 字段寬度列表(用空格鍵分隔)。
FILENAME 當前文件名。
FNR 同NR,但相對於當前文件。
FS 字段分隔符(默認是任何空格)。
IGNORECASE 若是爲真,則進行忽略大小寫的匹配。
NF 當前記錄中的字段數。
NR 當前記錄數。
OFMT 數字的輸出格式(默認值是%.6g)。
OFS 輸出字段分隔符(默認值是一個空格)。
ORS 輸出記錄分隔符(默認值是一個換行符)。
RLENGTH 由match函數所匹配的字符串的長度。
RS 記錄分隔符(默認是一個換行符)。
RSTART 由match函數所匹配的字符串的第一個位置。
SUBSEP 數組下標分隔符(默認值是\034)。
運算符 描述
= += -= *= /= %= ^= **= 賦值
?: C條件表達式
|| 邏輯或
&& 邏輯與
~ ~! 匹配正則表達式和不匹配正則表達式
< <= > >= != == 關係運算符
空格 鏈接
+ - 加,減
* / & 乘,除與求餘
+ - ! 一元加,減和邏輯非
^ *** 求冪
++ -- 增長或減小,做爲前綴或後綴
$ 字段引用
in 數組成員
通常通用的元字符集就不講了,可參考個人Sed和Grep。如下幾個是gawk專用的,不適合unix版本的awk。
\Y
匹配一個單詞開頭或者末尾的空字符串。
\B
匹配單詞內的空字符串。
\<
匹配一個單詞的開頭的空字符串,錨定開始。
\>
匹配一個單詞的末尾的空字符串,錨定末尾。
\w
匹配一個字母數字組成的單詞。
\W
匹配一個非字母數字組成的單詞。
\‘
匹配字符串開頭的一個空字符串。
\'
匹配字符串末尾的一個空字符串。
下面列舉awk編程須要瞭解的東西:
變量
BEGIN模塊
END模塊
重定向和管道
條件語句
if語句
if/else語句,用於雙重判斷。
if/else else if語句,用於多重判斷。
循環
數組
下標與關聯數組
awk的內建函數
字符串函數
時間函數
日期和時間格式說明符
內建數學函數
自定義函數
last會列出最近登陸的狀況, 僅取出前五行
假設last -n 5的輸出以下
[root@www ~]# last -n 5 root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41) root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48) dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00) root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
若是隻是顯示最近登陸的5個賬號 也就是第一列
#last -n 5 | awk '{print $1}' root root root dmtsai root
awk工做流程是這樣的:讀入有'\n'換行符分割的一條記錄,而後將記錄按指定的域分隔符劃分域,填充域,$0則表示全部域,$1表示第一個域,$n表示第n個域。默認域分隔符是"空白鍵" 或 "[tab]鍵",因此$1表示登陸用戶,$3表示登陸用戶ip,以此類推。
默認域分隔符是"空白鍵" 或 "[tab]鍵",若是想用其它符合做分隔符,參照下例:
/etc/passwd中是用:分割的
以下:
#cat /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin sys:x:80:80:desktop:/var/lib/menu/kde:/sbin/nologin
若是隻是顯示/etc/passwd的帳戶
#cat /etc/passwd |awk -F ':' '{print $1}' root daemon bin sys
-F指定域分隔符爲':'。 {print $1}輸出第一列
顯示/etc/passwd的帳戶和帳戶對應的shell,顯示時帳戶與shell之間以tab鍵分割
#cat /etc/passwd |awk -F ':' '{print $1"\t"$7}' root /bin/bash daemon /bin/sh bin /bin/sh sys /bin/sh
-F指定域分隔符爲':'。 {print $1 "\t" $7} 輸出第一列 tab 和 第7列
顯示/etc/passwd的帳戶和帳戶對應的shell,而帳戶與shell之間以逗號分割,並且在全部行添加列名name,shell,在最後一行添加"blue,/bin/nosh"。
#cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}' name,shell root,/bin/bash daemon,/bin/sh bin,/bin/sh sys,/bin/sh blue,/bin/nosh
awk工做流程是這樣的:先執行BEGING,而後讀取文件,讀入有/n換行符分割的一條記錄,而後將記錄按指定的域分隔符劃分域,填充域,$0則表示全部域,$1表示第一個域,$n表示第n個域,隨後開始執行模式所對應的動做action。接着開始讀入第二條記錄······直到全部的記錄都讀完,最後執行END操做。
搜索/etc/passwd裏有root關鍵字的全部行
#awk -F ':' '/root/' /etc/passwd root:x:0:0:root:/root:/bin/bash
這種是pattern的使用示例,匹配了pattern(這裏是root)的行纔會執行action(沒有指定action,默認輸出每行的內容)。
搜索支持正則,例如找root開頭的: awk -F ':' '/^root/' /etc/passwd
搜索/etc/passwd有root關鍵字的全部行,並顯示對應的shell 也就是第7列
# awk -F ':' '/root/{print $7}' /etc/passwd /bin/bash
這裏指定了action{print $7}
咱們上面提過都有哪些環境變量。
如今咱們要統計/etc/passwd文件中的:文件名,每行的行號,每行的列數
使用到的變量參數以下:
FILENAME awk瀏覽的文件名
NR 已讀的記錄數 也就是第幾行
NF 瀏覽記錄的域的個數 也就是 共幾列
$0 輸出整行
#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
printf就是線使用佔位符佔位,後面再一塊兒傳入參數,可讓代碼更加簡潔,易讀
awk -F ':' '{printf("filename:%s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
統計/etc/passwd的帳戶人數,每一行是一個帳戶,由於恰好awk是逐行遍歷,因此咱們自定義一個count自加就行。
固然 定義count爲0須要在 awk逐行遍歷以前 因此須要用BEGIN模塊。
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd [start]user count is 0 root:x:0:0:root:/root:/bin/bash ... [end]user count is 40
咱們須要統計某個文件夾下的文件佔用的字節數
由於文件佔用的字節數 在 ls -l命令中的第5列
因此咱們使用以下命令:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}' [end]size is 8657198
若是以M爲單位顯示:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}' [end]size is 8.25889 M
注意,統計不包括文件夾的子目錄。
統計某個文件夾下不等於4096的其它文件佔用的字節數-----過濾4096大小的文件:
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' [end]size is 8.22339 M
顯示/etc/passwd的帳戶
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd 0 root 1 daemon 2 bin 3 sys 4 sync 5 games ......
awk編程的內容極多,這裏只羅列簡單經常使用的用法,更多請參考 http://www.gnu.org/software/gawk/manual/gawk.html