linux實戰(一)----日誌的截取-----文本過濾器grep、文本流式編輯器sed、報表生成器awk的運用

linux實戰(一)----日誌的截取-----文本過濾器grep、文本流式編輯器sed、報表生成器awk的運用

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命令能夠指定文件中搜索特定的內容,並將含有這些內容的行標準輸出。

 

 

grep全稱是Global Regular Expression Print,表示全局正則表達式版本,它的使用權限是全部用戶。

 

格式

grep [options]

[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 經常用於一整個行的處理。sed是一種在線編輯器,它一次處理一行內容。處理時,把當前處理的行存儲在臨時緩衝區中,稱爲「模式空間」(pattern space),接着用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往屏幕。接着處理下一行,這樣不斷重複,直到文件末尾。文件內容並無 改變,除非你使用重定向存儲輸出。Sed主要用來自動編輯一個或多個文件;簡化對文件的反覆操做;編寫轉換程序等。

 

 

格式

sed [options] 'command' file(s)  
sed [options] -f scriptfile file(s)  

[options]主要參數

-n :使用安靜(silent)模式。在通常 sed 的用法中,全部來自 STDIN 的數據通常都會被列出到終端上。但若是加上 -n 參數後,則只有通過sed 特殊處理的那一行(或者動做)纔會被列出來。

-e :直接在命令列模式上進行 sed 的動做編輯;
-f :直接將 sed 的動做寫在一個文件內, -f filename 則能夠運行 filename 內的 sed 動做;
-r :sed 的動做支持的是延伸型正規表示法的語法。(默認是基礎正規表示法語法)
-i :直接修改讀取的文件內容,而不是輸出到終端。
 

'command'主要參數

 

a :新增, a 的後面能夠接字串,而這些字串會在新的一行出現(目前的下一行)~
c :取代, c 的後面能夠接字串,這些字串能夠取代 n1,n2 之間的行!
d :刪除,由於是刪除啊,因此 d 後面一般不接任何咚咚;
i :插入, i 的後面能夠接字串,而這些字串會在新的一行出現(目前的上一行);
p :列印,亦即將某個選擇的數據印出。一般 p 會與參數 sed -n 一塊兒運行~
s :取代,能夠直接進行取代的工做哩!一般這個 s 的動做能夠搭配正規表示法!例如 1,20s/old/new/g 就是啦!

 

pattern正則表達式主要參數

 ^    行首定位符           

 

/^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將處理輸入文件的全部行。 
地址是一個數字,則表示行號;是「$"符號,則表示最後一行。

 

 

 

實例

刪除d命令

 

$ sed '2d' example

 

刪除example文件的第二行。

 

 

$ sed '2,$d' example

 

刪除example文件的第二行到末尾全部行。

 

 

 

$ sed '$d' example

 

刪除example文件的最後一行。

 

 

 

$ sed '/test/'d example

 

刪除example文件全部包含test的行。

 

 

替換s命令

 

 

$ 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替換。

 

 

多點編輯e命令

 

 

$ 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表達式賦值。

 

 

從文件讀入r命令

 

 

$ sed '/test/r file' example

 

file裏的內容被讀進來,顯示在與test匹配的行後面,若是匹配多行,則file的內容將顯示在全部匹配行的下面。

 

 

寫入文件w命令

 

 

$ sed -n '/test/w file' example

 

在example中全部包含test的行都被寫入file裏。

 

 

追加命令a命令

 

 

$ sed '/^test/a\\this is a test line'  example

 

在example文件中'this is a test line'被追加到以test開頭的行後面,sed要求命令a後面有一個反斜槓。

 

插入i命令

 

$ sed '/test/i\\new line-------------------------'   example

若是test被匹配,則把反斜槓後面的文本插入到匹配行的前面。

 

 

下一個n命令

 

$ sed '/test/{ n; s/aa/bb/; }'  example

 

若是test被匹配,則移動到匹配行的下一行,替換這一行的aa,變爲bb,並打印該行,而後繼續。

 

 

變形y命令

 

 

$ sed '1,10y/abcde/ABCDE/' example

 

把1--10行內全部abcde轉變爲大寫,注意,正則表達式元字符不能使用這個命令。
 

 

退出q命令

 

$ sed '10q' example

 

打印完第10行後,退出sed。

 

 

保持和獲取h命令和G命令

 

 

$ sed -e '/test/h' -e '$G example

 

在sed處理文件的時候,每一行都被保存在一個叫模式空間的臨時緩衝區中,除非行被刪除或者輸出被取消,不然全部被處理的行都將打印在屏幕上。接着模式空間被清空,並存入新的一行等待處理。在這個例子裏,匹配test的行被找到後,將存入模式空間,h命令將其複製並存入一個稱爲保持緩存區的特殊緩衝區內。第二條語句的意思是,當到達最後一行後,G命令取出保持緩衝區的行,而後把它放回模式空間中,且追加到如今已經存在於模式空間中的行的末尾。在這個例子中就是追加到最後一行。簡單來講,任何包含test的行都被複制並追加到該文件的末尾。
 

 

保持和互換h命令和x命令

 

$ sed -e '/test/h' -e '/check/x' example

 

互換模式空間和保持緩衝區的內容。也就是把包含test與check的行互換。

 

 

 

awk

做用

 

 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域分隔符的狀況下,默認的域分隔符是空格。

 

commands

awk的命令很是多,由於它甚至能夠算是一個編程語言。咱們這裏就不詳細講述了。後面的實例學習中會了解到一部分經常使用的命令。

這裏大概給出awk中的一些學習目錄以下:

 

print和printf

awk中同時提供了print和printf兩種打印輸出的函數。
其中print函數的參數能夠是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。若是沒有逗號,參數就串聯在一塊兒而沒法區分。這裏,逗號的做用與輸出文件的分隔符的做用是同樣的,只是後者是空格而已。
printf函數,其用法和c語言中printf基本類似,能夠格式化字符串,輸出複雜時,printf更加好用,代碼更易懂。

 

 

 

awk的環境變量

變量描述
$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)。
 

 

awk運算符

運算符 描述
= += -= *= /= %= ^= **= 賦值
?: C條件表達式
|| 邏輯或
&& 邏輯與
~ ~! 匹配正則表達式和不匹配正則表達式
< <= > >= != == 關係運算符
空格 鏈接
+ - 加,減
* / & 乘,除與求餘
+ - ! 一元加,減和邏輯非
^ *** 求冪
++ -- 增長或減小,做爲前綴或後綴
$ 字段引用
in 數組成員

 

 

 

專屬正則表達式元字符

通常通用的元字符集就不講了,可參考個人Sed和Grep。如下幾個是gawk專用的,不適合unix版本的awk。
\Y
匹配一個單詞開頭或者末尾的空字符串。
\B
匹配單詞內的空字符串。
\<
匹配一個單詞的開頭的空字符串,錨定開始。
\>
匹配一個單詞的末尾的空字符串,錨定末尾。
\w

 

匹配一個字母數字組成的單詞。
\W
匹配一個非字母數字組成的單詞。
\‘
匹配字符串開頭的一個空字符串。
\'
匹配字符串末尾的一個空字符串。

 

 

 

awk編程

下面列舉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列

 

 

 

使用BEGIN END模塊

顯示/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}

 

 

 

 

awk環境變量的運用

咱們上面提過都有哪些環境變量。
如今咱們要統計/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替代print

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

相關文章
相關標籤/搜索