Linux的文本三劍客(grep sed awk) —— awk的介紹

一、三劍客簡介

     grep: 文本過濾工具, (grep,egrep,fgrep)  文本搜索工具,根據用戶指定的“模式”對目標文件逐步進行匹配檢查,打印匹配到的行。

     sed: 文本編輯工具,實現數據的替換,刪除,增加,選取等(以行爲單位進行處理)。

     awk: 文本報告生成器,以字段爲單位進行處理(把一行的數據分割,然後進行處理)。

     本文只介紹awk。

awk的介紹

    1. awk的簡介

     awk不僅是linux系統中的一個命令,還是一種編程語言,可以用來處理數據和生成報告(excel)。處理的數據可以是一個或多個文件,可以是來自標準輸入,也可以通過管道獲取標準輸入,awk可以在命令行上直接編輯命令進行操作,也可以編寫成awk程序來進行更爲複雜的運用。

     awk的應用裏最重要的一個功能就是計數,而數組在awk裏最大的作用就是去重複。

     2. awk的格式

    awk指令是由模式,動作,或者模式和動作的組合組成。

    awk  [options] 'pattern{print} ' file

    模式既pattern,可以類似理解成sed的模式匹配,可以由表達式組成,也可以是兩個正斜槓之間的正則表達式。比如NR==1,這就是模式,可以把他理解爲一個條件。     動作即action,是由在大括號裏面的一條或多條語句組成,語句之間使用分號隔開。

image.png

image.png

   注意:

     pattern和{action}需要用單引號引起來,防止shell作解釋。

     pattern是可選的。如果不指定,awk將處理輸入文件中的所有記錄。如果指定一個模式,awk則只處理匹配指定的模式的記錄。

    {action}爲awk命令,可以是但個命令,也可以多個命令。

    整個action(包括裏面的所有命令)都必須放在{  }內。

    action必須被{ }包裹,沒有被{ }包裹的就是patern

    file要處理的目標文件

     3. awk工作原理

      awk 程序通常由:BEGIN語句塊、能夠使用模式匹配的通用語句塊、END語句塊,共3部分組成。

      第一步:執行BEGIN{action;… }語句塊中的語句。

      第二步:從文件或標準輸入讀取一行,然後執行pattern{ action;… }語句塊,逐行掃描文件,從第一行到最後一行重複這個過程,直到文件全部被讀取完畢。
      第三步:當讀至輸入流末尾時,執行END{action;…}語句塊。

      BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中。

      END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如打印所有行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊。

     pattern語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。

    4. 記錄與字段

   awk對每個要處理的輸入數據認爲都是具有格式和結構的,而不僅僅是一堆字符串。默認情況下,每一行內容都是一條記錄,並以換行符分隔(\n)結束。

    簡單來說:     記錄  =  行

                     字段,域  =  列

    小結:

    RS  記錄分隔符,表示每行的結束標誌
    NR  行號(記錄號)
    FS  字段分隔符,每列的分隔標誌或結束標誌
    NF  就是每行有多少列,每個記錄中字段的數量
    $  符號表示取某個列(字段),$1$2$NF
    NF  表示記錄中的區域(列)數量,$NF取最後一個列(區域。)
    FS(-F)字段(列)分隔符,-F(FS)“:”<==>‘BEGIN{FS=':'}’
    NR  行號
    分隔符==>結束標識

  5. awk變量

    1,內置變量

FS:輸入字段分隔符

 awk -v FS=':' '{print $1,$3}' /etc/passwd

     先找一個文件/etc/passwd作爲參數,這樣可查看命令的結果。

image.png

image.png

OFS:輸出字段分隔符

awk -v FS=':' -v OFS=':' '{print $1,$3}' /etc/passwd

image.png

RS:輸入的記錄分隔符

awk -v FS="." -v RS=" " '{print $1}' chen

image.png

ORS:輸出的記錄分隔符

awk -v FS="." -v RS=" " -v ORS="#" '{print $1}' chen

image.png

NF:字段的數量

awk -F" " '{print NF}' /etc/fstab

image.png

image.png

NR:記錄號

awk '{print NR,$0}' /etc/fstab

image.png

FNR:各文件分別計數,行號

awk '{print FNR}' /etc/fstab /etc/inittab

image.png

FILENAME:當前文件名

awk '{print FILENAME}’ /etc/fstab

image.png

ARGC:命令行參數的個數

awk '{print ARGC}' /etc/fstab  /etc/shadow

image.png

ARGV:數組,保存的是命令行所給定的各參數

awk 'BEGIN {print ARGV[2]}'  /etc/fstab /etc/inittab

image.png

打印命令行的最後一個參數

awk 'BEGIN {print ARGV[ARGC-1]}'  /etc/fstab /etc/inittab /etc/haha hi hello

image.png

  2,自定義變量

    (1) -v var=value
    (2) 在program中直接定義

image.png

image.png

image.png

image.png

    6. 輸出命令

   1,輸出命令:print

    用法:print item1,item2,...

           item:字符串,用引號引用;

           變量:顯示變量的值,可以直接使用變量的名進行引用;

           數值:不加引號

    要點:

       (1)各item之間使用逗號分隔;輸出的分隔符默認爲空白字符;

       (2)輸出的各item可以爲字符串或數值、當前記錄的字段($#)、變量或awk的表達式;數值會被飲食轉換爲字符串進行輸出;

       (3)print後的item省略時,相當於運行"print $0" ,用於輸出整行;

       (4)輸出空白字符:print " "

 2,格式化輸出:printf

    用法:printf “FORMAT”, item1, item2, ...

    (1)必須指定FORMAT;
    (2) 不會自動換行,需要顯式給出換行控制符,\n;
    (3)FORMAT中需要分別爲後面每個item指定格式符;

   格式符:與item一一對應
    %c: 顯示字符的ASCII碼
    %d, %i: 顯示十進制整數
    %e, %E:顯示科學計數法數值
    %f:顯示爲浮點數
    %g, %G:以科學計數法或浮點形式顯示數值
    %s:顯示字符串
    %u:無符號整數

    %%: 顯示%自身

   舉例:

awk -F: '{printf "Username:%s UID:%s\n",$1,$3}' /etc/passwd

image.png


awk -F: '{printf "Username:%-15s UID:%s\n",$1,$3}' /etc/passwd

image.png

awk -F: 'BEGIN{printf "%.d %.2f\n",1.73333,3.1111}'

image.png

   修飾符:

    #[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後精度,%3.1f
    -: 左對齊(默認右對齊) %-15s
    +:顯示數值的正負符號 %+d

   7. awk操作符

   1, 算術操作符:
   x+y, x-y, x*y, x/y, x^y, x%y
  -x: 轉換爲負數

  +x: 轉換爲數值

awk 'BEGIN{print 2^5}

image.png

    2, 字符串操作符:沒有符號的操作符,字符串連接

    3, 賦值操作符:

   =, +=,
   -=, *=, /=, %=, ^=

   ++, --

awk 'BEGIN{print i++;print i}'
awk 'BEGIN{print ++i;print i}'

image.png

    4, 比較操作符:

   ==, !=, >, >=, <, <=

awk -v FS=: '$3 == 0 {print $0}' /etc/passwd

image.png

    5, 模式匹配符:

    ~:左邊是否和右邊匹配包含
    !~:是否不匹配


awk '$0 ~ "^root" {print $0}' /etc/passwd

image.png

    6, 邏輯操作符:與&&,或||,非!

awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd

image.png    

    7, 函數調用: function_name(argu1, argu2, ...)
    8, 條件表達式(三目表達式):
selector?if-true-expression:if-false-expression

   9,關係表達式
   爲非0時,即爲真,才處理
   爲0或爲空時,不處理

    !0=1  !Num=0  (Num爲任意非0的值)

   舉例:

df |awk -v FS=% '$0 ~ "/dev/sd" {print $1}'|awk '$NF>=10 {printf "DevName:%-10s Used:%s%%\n",$1,$5}'

image.png

   8. PATTERN

     PATTERN:根據pattern條件,過濾匹配的行,再做處理
     (1)如果未指定:空模式,匹配每一行
     (2) /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來

awk '/^UUID/{print $1}' /etc/fstab
awk '!/^UUID/{print $1}' /etc/fstab

image.png

    (3) relational expression: 關係表達式,結果爲“真”纔會被處理
    真:結果爲非0值,非空字符串
    假:結果爲空字符串或0值

    (4) 行範圍:類似於vim sed 中的地址定界方式

cat /boot/grub/grub.conf |awk '/default/,/hidden/' 匹配以'/default/開始,以/hidden/結束'的範圍

image.png

    (5) BEGIN/END模式
    BEGIN{ }:僅在開始處理文件中的文本之前執行一次
    END{ }:僅在文本處理完成之後執行

    9. 控制語句

   1,if-else

   語法:

     if(condition){statement;…}[else statement]
     if(condition1){statement1}else if(condition2){statement2}
     else{statement3}
   使用場景:

     對awk取得的整行或某個字段做條件判斷

awk -v FS=: '{if($3>=1000){usertype="Common User"}else{usertype="Sys User"}printf "UserName:%-15s Type:%s\n",$1,usertype}' /etc/passwd

image.png

   2,while循環

  語法:

      while(condition){statement;…}

    條件“真”,進入循環;條件“假”,退出循環
 使用場景:
     對一行內的多個字段逐一類似處理時使用
     對數組中的各元素逐一處理時使用

echo {1..10} |awk '{n=1;while(n<=NF){if($n%2==0){print $n,"oushuo"}eelse {print $n,"jishu"};n++}}'

image.png


    3,do-while循環

  語法:do {statement;…}while(condition)

  意義:無論真假,至少執行一次循環體

    4,for循環
  語法:for(expr1;expr2;expr3) {statement;…}
  常見用法:
     for(variable assignment;condition;iteration process)
     {for-body}
  特殊用法:能夠遍歷數組中的元素
  語法:for(var in array) {for-body}

    5, switch語句

  語法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}

   6, break和continue

    break[n]:退出當前循環,n爲數字,用於指定推出幾層循環;

    continue:提前結束本輪循環而進入下一輪;

awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i};print sum}'

image.png

awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i};print sum}'

image.png

  7,next:提前結束對本行處理而直接進入下一行處理(awk自身循環)

image.png

awk -v FS=: '{if($3%2!=0) next;print $1,$3}' /etc/passwd

image.png

    10. 數組

    關聯數組:array[index-expression]
     index-expression:
    (1) 可使用任意字符串;字符串要使用雙引號括起來
    (2) 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,並將其值初始化爲“空串”;要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷。

     數組遍歷:

   若要遍歷數組中的每個元素,要使用for循環
   for(var in array) {for-body}
    注意:

    var會遍歷array的每個索引

image.png

     11. 函數 

       函數分爲內建函數和用戶自定義函數

        1,內建函數

        數值處理rand():返回0至1之間的一個隨機數;

awk 'BEGIN{srand();print int(rand()*10000)}'

image.png

        字符串處理:

         length([s]):返回指定的字符串的長度。

awk 'BEGIN{print length("hello")

image.png

         sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並將第一個匹配的內容替換爲s。

echo "2018:08:29 10:08:30" |awk 'sub(/:/,"-",$1)'

image.png

         gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並全部替換爲s所表示的內容。

echo "2018:08:08 08:08:08" |awk 'gsub(/:/,"-",$1)'  匹配第一字段
echo "2018:08:08 08:08:08" |awk 'gsub(/:/,"-",$0)'  匹配所有

image.png

image.png

         split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存至array所表示的數組中。

netstat -tan

image.png

netstat -tan |awk '/^tcp\>/&& !($5 ~ "*") {split($5,ip,":");count[ip[1]]++}ENcount[ip[1]]++}END{for(i in count){print i,count[i]}}'

image.png

           注意:awk的數組下標從開始編號。

         substr(s,i[,n]):從s所表示的字符串中取出字串。取法:從i表示的位置開始,取n個字符。

三、總結

記住三個命令的運用形式
     grep    '字符'       文件
     sed     '命令'       文件
     awk    '條件{命令}'   文件

單引號內就是正則表達式的用法

重複一遍:單引號內一定是正則表達式!



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