Linux中Regex與檔案格式化處理命令(awk/grep/sed)

來源:互聯網
上載者:User
一.Regex1.1國際字元模式比對或匹配模式的類名

[:alnum:] : 0-9,A-Z,a-z
[:alpha:] : A-Z,a-z
[:upper:] : A-Z
[:lower:] : a-z
[:digit:] : 0-9
[:space:] : 空格或tab鍵

1.2基礎Regex

^word:待尋找的字串在行首。
word$:待尋找的字串在行尾。
. :代表一定有一個任一字元的字元。
\ :逸出字元,將特殊符號的意義去除。
* :重複0個到無窮多個的前一個字元。
[list]:從字元集合的RE字元裡面找出想要選取的字元,在[]當中代表一個待尋找的字元;
        例如:[afg]代表a或f或g的意思。
[n1-n2]:代表想要找出的字元範圍;
        eg:[0-9]表示0到9;[a-z]代表a到z。
[^list]:找出不要的字串或範圍,即找出不含list中字串的;
        eg:[^A-Z]:代表不要非大寫字母;[^t]:不要字母t。
\{n,m\}:相當於{n,m}的轉義,因{的轉義為\{,因}的轉義為\},表示連續n到m個前一個字元。
\{n\}:相當於{n},即表示重複n個前一個字元。
\{n,\}:相當於{n,},表示連續n個以上的前一個字元。
註:Regex的特殊字元與一般命令列輸入命令的“萬用字元”並不相同。在萬用字元中*表示0到無限多個字元。但在Regex中,*則是0到無窮多個前一個字元。
eg:尋找以a開頭的檔案名稱的兩種實現:
萬用字元: ls -l a*
Regex:ls -l | grep '^a.*' 

1.3擴張Regex

grep預設只支援基礎Regex,如果使用擴充性運算式,可以使用grep -E,不過更建議直接使用egrep。egrep == grep -E。
+ :重複一個或一個以上的前一個RE字元。
    eg:egrep -n 'go+d' a.txt
    即god,good,goood,...。
? :0個或1個的前一個RE字元。
    eg: egrep -n 'go?d' a.txt
    即gd,god,good,...。
| :用或(or)的方式找出數個字串。
    eg:egrep -n 'gd|god' a.txt
    尋找含gd或good的行。
():找出‘組’字串
    eg:egrep -E 'g(la|oo)d' a.txt
    找出glad或good的行。
()+:多個重複的群組的判別
    eg:egrep 'A(xyz)+C' a.txt
    開頭為A,結尾為C,中間位1一個以上的xyz字串。

註:RE:regular expression(Regex)。

二.awk命令
2.1awk概述

互連網中對日誌分析,大多使用的是linux中的shell進行處理。此時主要使用的shell中的awk,因為awk強大的欄位處理能力。下面就對其由淺入深,最後給出執行個體進行講解。

首先給出一個很好的awk學習連結:http://www.cnblogs.com/chengmo/tag/awk/ 。

awk比較傾向於將一行分成數個“欄位”來處理,其運行模式為:

awk '條件類型1{動作1} 條件類型2{動作2}...'   filename

註:awk主要是處理每一行的欄位內的資料,而預設的欄位的分隔字元為空白格鍵或tab鍵。

2.2awk入門

(1)eg: last -n 5 | awk '{print $1 "\t" $3}'

表示將登陸者的資料取出來,僅取前5行。其中$1表示當前行的第一個資料;$3表示當前行的第三個資料。

(2)awk是如何知道這個資料有幾行幾列呢?這需要下面的內建變數進行幫忙:

NF:每一行($0)的欄位總數;NR:目前awk所處理的是第幾行;FS:目前的分隔字元,預設為空白格鍵。

eg:在/etc/passwd當中是以冒號來作為欄位分隔符號的,該檔案第一個欄位為帳號,第3個欄位為UID,那下面要查詢第3列小於10以下的資料,並且僅列出第一列與第三列,可以如下做:

cat /etc/passwd | awk ‘BEGIN{FS=":"} $3<10{print $1 "\t" $3}’

輸出如下:

root 0

bin  1

註:BEGIN:讓使用者指定在第一條輸入記錄被處理之前所發生的動作,通常可在這裡設定全域變數。END:讓使用者在最後一條輸入記錄被讀取之後發生的動作。

(3)有如下的薪資表pay.txt,內容如下:

Name   1st           2st        3st

Sean   23000    24000    25000

Zhao   21000    20000    23000

Bird2   43000    42000   41000

那如何格式化輸出,並能計算每個人的總額呢?

如下考慮:第一行不需要加總,只是說明(NR==1);第二行以後,有加總(NR>=2)。

命令如下:

cat pay.txt | awk '{

if(NR==1)

    printf  "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}

NR>=2{

     total=$2+$3+$4 

     printf "%10d %10d %10d %10d %10.2f\n ",$1,$2,$3,$4,total }'

也可以這樣:

cat pay.txt | awk 'NR==1{

    printf  "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}

NR>=2{

     total=$2+$3+$4 

     printf "%10d %10d %10d %10d %10.2f\n ",$1,$2,$3,$4,total }'

(4)如何查看一個檔案的最後5行:tail -n 5 a.txt

如何查看有一個檔案的前5行:head -n 5 a.txt

列印檔案的行數:awk ‘END{print NR}’  data.txt  

(5)如何查看一個檔案夾下檔案的個數

ls -l | awk 'END{print NR}'

註:表示處理完最後一行的時候,輸出當前的NR,即檔案的總行數。

(6)每4行轉換成一行

awk '{if(NR%4==0){print $0}else{printf "%s",$0}}'  a.xml

2.3awk的實際應用

現在給出日誌資料,只給出幾行,如下所示:

23:59:59        bj      other   other1  detail  1       0       8178526912798594496654
23:59:59        ly       fang    fang1   list     34      2       7564641773641447038883
23:59:59        bj      fang    fang1   detail  1       0       4062479590911058005479
23:59:59        bj      fang    fang1   detail  1       0       7311067232020513225874

(1)awk統計日誌中的pv和uv

pv表示頁面的訪問量,即重新整理一次算一次訪問。uv表示訪客數,即訪問這個頁面的使用者數。

下面實現統計該日誌中的所有pv和uv,同時統計每一個大類(第三列資料)的pv和uv,shell如下所示:

#!/bin/shif [ $# -lt 1 ]; then    echo "Usage:"    echo "      $0 [filename]"    exit 1fiif [ "$1" == "-h" ]; then    echo "Usage: $0 [filename]"    exit 1fiawk -F"\t" '{    total[$8] ++;    uvlist[$3"#"$8] ++;    if($5 == "detail")    {        detailpv ++;        pvlist[$3] ++;    }}END{    print "total\t"detailpv"\t"length(total)    for(k in uvlist)    {        split(k, c, "#");        cate[c[1]] ++;    }    for(k in pvlist)    {        print k"\t"pvlist[k]"\t"cate[k];    }}' $1

運行結果如下:

(2)awk從日誌中統計線上率

這裡統計是根據第二列(城市)和第三列(大類)進行統計的。shell如下:

#!/bin/shif [ $# -lt 1 ]; then        echo "Usage:"        echo "      $0 [filename]"        exit 1fiif [ "$1" == "-h" ]; then        echo "Usage: $0 [filename]"        exit 1ficat $1 | awk -F"\t"  '$5 == "list"{    if($2 != "bj" && $2 !="sh" && $2 != "gz" && $2 != "sz") next;    citycategory = $2"_"$3;    citymajor = $2"_"$4;    if($3 == "fang")    {        ctotal[citymajor] += $6;        conline[citymajor] += $7;    }    ctotal[citycategory] += $6;    conline[citycategory] += $7;    listall += $6;    listonlineall += $7;}$5 == "detail"{    if($2 != "bj" && $2 !="sh" && $2 != "gz" && $2 != "sz") next;    citycategory = $2"_"$3;    citymajor = $2"_"$4;    if($3 == "fang")    {        dctotal[citymajor] += $6;        dconline[citymajor] += $7;    }    dctotal[citycategory] += $6;    dconline[citycategory] += $7;    detailall += $6;    detailonlineall += $7;}END{    #按城市和大類一起統計    cslen=asorti(ctotal,clA);    print "<table border=\"1\"><caption align=\"top\">使用者線上率統計</caption><tr><td>城市</td><td>類別</td><td>列表頁總人數</td><td>列表頁線上率</td><td>詳情頁總人數</td><td>詳情頁線上率</td></tr>";    for(i=1; i <= cslen; i ++)    {        split(clA[i], arr, "_");        dc = dct = "-";        if(clA[i] in dctotal)        {            dct = dctotal[clA[i]];            dc = dconline[clA[i]]/dct;        }        printf("<tr><td>%s</td><td>%s</td><td>%d</td><td>%.2f%%</td><td>%d</td><td>%.2f%%</td></tr>", arr[1], arr[2], ctotal[clA[i]], conline[clA[i]]*100/ctotal[clA[i]], dct, dc *100);    }    print "</table><br/><br/>";}'

三.grep命令3.1grep概述

grep:進行字元的對比,將符合要求的字元列印出來。是以Regex搜尋文本,並列印匹配行。grep是以整行為單位來進行資料的選取的。

其格式: grep [option] 'Regex' 檔案名稱

option: -n表示列印出時,顯示行號;

               -v表示反向選擇,即不要符合Regex的行;

              -A:後可加數字,為after意思,除了該行外,後續的n行也可列出。eg:-A3

              -B:為before,除了該行外,前面的n行也可列出。

3.2grep入門

(1)尋找特定字串

grep -n 'the' a.txt :尋找含the的行,並顯示行號

grep -vn 'the' a.txt:尋找不含the的行,並顯示行號

grep -in ‘the’ a.txt:忽略the的大小寫,尋找含the的行,即the、The、tHe......

(2)尋找字元集合,利用[]

grep -n 't[ae]st' a.txt :尋找含tast或test的行

grep -n '[^g]oo' a.txt :oo前面不要出現g

grep -n '[^a-z]oo' a.txt :不想oo前面含小寫字母,等價於grep -n '[^[:lower:]]oo' a.txt
(3)行首與行尾字元^$

(a)grep -n '^[^a-zA-Z]' a.txt   :不要以字母開頭的行

等價於grep -n '^[^[:alpha:]]' a.txt

註:^在[]之外表示定位在行首。^在[]之內表示“反向選擇”。

(b)grep -n '\.$' a.txt:以.結束的行。因.表示任一字元,所以是特殊符號,需要轉義。

(c)grep -n '^$' a.txt:找出哪些行是空行。

(d)grep -v '^$' a.txt  | grep -v '^#':不要空行和以“#”開頭的行。

(4)任意一個字元.與重複字元*

grep -n 'g..g' a.txt  :表示g__g的字元

grep -n 'g*g' a.txt:g*表示一個Null 字元或一個以上的g,再加上後面的g。

grep -n ‘g.*g’ a.txt:表示g開頭與g結尾。*表示0個或任意多個字元。

(5)限定連續RE字元的範圍

因{}在shell中是有特殊意義的,因此我們必須用逸出字元\來讓它失去特殊意義才行的。

grep -n 'go\{2,\}g' a.txt:表示含2個以上的o。即good、goood、....

四.sed命令4.1sed概述

sed常用於一整行的處理,主要對檔案中的行進行操作。

其格式為:sed [-nefr] [動作]

動作說明:[定址] function

定址方式如下:
(1)n1[,n2]:表示n1到n2之間進行動作。eg:10,20[動作行為]
(2)/pattern/:模式(Regex)pattern指定的行
(3)/pattern/,/pattern/:2個模式(Regex)之間的行進行動作
(4)/pattern/,x:模式+行(在給定行號上查詢模式)
(5)x,y/pattern/:通過行號和模式比對行
(6)x,y!:不包含指定行號
(7)$:表示最後一行
註:範圍可通過數值,Regex或者二者結合的方式確定。

fuction(即動作)如下:
(1)a:append(新增),在目前定址行的下一行插入字串
(2)c:change(替換),替換當前定址到的行為字串
(3)d:delete(刪除),刪除當前定址的行
(4)i:insert(插入),在定址行的上一行插入字串
(5)p:print(列印),列印當前定址行的資料
(6)s:substitute(替換),其格式為:'s/要替換的字串/新的字串/g'

註:a、c、i動作之後,可以用空格或“\”隔開字串

4.2sed入門

(1)以行為單位的新增功能
註:新增操作,結果到標準輸出,不能被編輯,必須存到另一檔案中。

在匹配行的下一行插入一行:
sed '/dreamb/a\appended line' a.txt :表示將含“dreamb”的匹配行後插入一行“appended line”
或 sed '/dreamb/a append line' a.txt
cat /etc/passwd | sed '2a drink tea':表示在第二行後追加一行“drink tea”
如果想儲存修改,一般是重新導向到另外的一個檔案。

sed '/five/i four' a.txt > result.txt:表示含“five”的匹配行的上一行插入一行“four”
如果想直接修改源檔案,可以用下面的命令:
sed -i '/five/i four' a.txt
(2)修改文本
sed '3c\changed line' a.txt :表示在第三行替換為“changed line”
等價於sed '3c changed line' a.txt
(2)刪除文本
sed '1,3d' a.txt:刪除1到3行
sed '/dreamd/d' a.txt:刪除含“dreamd”的行
sed -n '/Begin/,/End/d' a.txt | more:刪除兩個匹配行之間的資料
sed '$d' a.txt:刪除最後一行
sed '/^th/d' a.txt:刪除以th開頭的行
(3)替換
替換格式:sed '[address[,address]] s/pattern_find/replacement_pattern/[g,p,w,n]' filename

其中,g表示對模式空間中的所有情況進行替換,預設只替換首次出現的模式。
sed '1,2 s/d$/&dd' a.txt:將1-2行中的所有以d結尾的行,都附加上一個dd
sed '/first/ s/st/ST/' a.txt:將含有“first”的行中st換成大寫ST
cat /etc/man.config | grep 'MAN' | sed 's/#.*$'//g':表示刪除掉“#”批註之後的資料
(4)轉換檔
通常用於大小寫轉換
文法為:y/abc/xyz/
sed 'y/five/six1' a.txt:將five轉換成six1
(5)顯示匹配行
sed -n '5,7p' a.txt:顯示a.txt中的5-7行
等價於head -n 7 | tail -n 3:即前7行中的後3行

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.