awk

文本處理工具awk

1. 簡介

  • 來由與做用
    awk是由Aho, Weinberger, Kernighan三位大牛開發的程序,用於報告生成器,格式化文本輸出,可接收標準輸入
  • 版本php

  1. New awk(nawk)
  2. GNU awk( gawk),centos使用的爲gawk
  • 運行原理css

    1. 分割符、域和記錄linux

    1. awk執行時,由分隔符分隔的字段(域)標記1,1,0爲全部域,注意:和shell中變量$符含義不一樣
    2. 文件讀入內存空間的每一行稱爲記錄,文本中的一行能夠爲多個記錄
    3. 省略action,則默認執行 print $0 的操做
  • 工做原理nginx

    1. 執行BEGIN{action;… }語句塊中的語句
    2. 從文件或標準輸入(stdin)讀取一個記錄到內存空間,執行pattern{ action;… }語句塊,匹配預約義的模式,若是不匹配就不處理,匹配後按照預先規定好的分隔符切割成若干字段,分割成功後,系統會對這些列分配一個域標識$1..$n,直到文件所有被讀取完畢。
    3. 當讀至輸入流末尾時,執行END{action;…}語句塊web

    1. BEGIN語句塊在awk開始從輸入流中讀取行以前被執行,這是一個可選的語句塊,好比變量初始化、打印輸出表格的表頭等語句一般能夠寫在BEGIN語句塊中
    2. END語句塊在awk從輸入流中讀取完全部的行以後即被執行,好比打印全部行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊
    3. pattern語句塊中的通用命令是最重要的部分,也是可選的。若是沒有提供pattern語句塊,則默認執行{ print },即打印每個讀取到的行,awk讀取的每一行都會執行該語句塊

    2. 基本用法

    • 格式:
      awk [options] var=value ‘program’ file…
    • 選項(options):正則表達式

    1. -v var=value: 自定義變量
    2. -f programfile: 讀取文件中的程序
      awk [options] var=value -f programfile file…
    3. -F:指明輸入時用到的字段分隔符,分隔符能夠指定多個sql

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    示例:指定[;]爲記錄分隔符,下例爲2個記錄a:b@c:d與1:2@3 1:指定[:]爲字段分割符 $echo "a:b@c:d;1:2@3"|awk -v RS=";" -F":" '{print $1,$3}' a d 1 2:指定[@:]爲字段分割符 $echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"[@:]" '{print $1,$3}' a c 兩個分隔符都起做用,c爲第3個字段 1 3 3:以擴展正則表達式方法表示也能夠 $echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"@|:" '{print $1,$3}'
  • program
    爲awk本身的語法,一般是被單引號或雙引號中,建議使用單引號,由於雙引號在程序中會在字符串上用,避免混用shell

    1. 格式:
      1. BEGIN語句塊、可以使用模式匹配的通用語句塊、END語句塊,共3部分組成
        ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }’
      2. 經常使用格式:
        pattern{action statements;..}
    2. 釋義pattern和action:
      1. pattern部分決定動做語句什麼時候觸發及觸發事件
      2. action statements對數據進行處理,放在{ }內指明
        1. action格式: {print|printf item1, item2, …}
        2. 要點:
          1. 逗號分隔符
          2. 輸出的各item能夠字符串,也能夠是數值;當前記錄的字段、變量或awk的表達式
          3. 如省略item,至關於print $0
  • 示例
    例如:打印出/etc/passwd文件的第1和第3行express

  •  
     
     
     
     
    • 1
    awk -F: '{print $1,$3}' /etc/passwd

    3. awk變量

    變量:分爲內置和自定義變量,只要對變量賦值,就要放在選項-v的後面apache

    3.1 內置變量

    • FS(field separator):輸入字段分隔符,默認爲空白字符,指定變量的好處在於,能夠屢次調用

    1. 示例1:定義FS=’:’,在(程序)中調用變量

      $awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
      named:25
    2. 示例2:一次引用多個變量,中間須要使用逗號隔開

      $awk -v FS=: '{print $1FS,FS,FS$3}' /etc/passwd
      named: : :25
    3. 示例3:還能夠引用shell中的變量,先聲明fs=:,而後用awk調用

      $fs=:;awk -v FS="$fs" '{print $1FS$3}' /etc/passwd
      named:25
  • OFS(output field separator):指定輸出字段分隔符,默認爲空白字符

    1. 示例:以###做爲字段分隔符

      $awk -F":" -v OFS=### '{print $1,$3,$2}' /etc/passwd
      named###25###x
  • RS(record separator):輸入記錄分隔符,指定輸入時的換行符

    1. 示例:建立文本,以下awk.txt所示,[@,!,?]與[1,2,3,4]以及[A,B,C\naa,bb,cc],以[;]分隔開

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 建立實驗文本 $cat awk.txt @,!,?;1,2,3,4;A,B,C aa,bb,cc 2. 指定輸入字段分隔符爲[,],輸出字段分隔符爲[==],輸入記錄分隔符爲[;] $awk -v FS="," -v OFS="==" -v RS=";" '{print $3,$4}' awk.txt ?== <==第一個記錄@,!,?沒有第4個字段 3==4 <==第二個記錄1,2,3,4,顯示後兩個 C <==第三個記錄,保留原有格式換行,C\naa爲第三個字段 aa==bb
  • ORS:輸出記錄分隔符,輸出時用指定符號代替換行符

    1. 承上例,每條記錄輸出時默認爲換行處理,能夠經過ORS指定

     
     
     
     
     
    • 1
    • 2
    • 3
    $awk -v FS="," -v OFS="==" -v RS=";" -v ORS="***" '{print $3,$4}' awk.txt ?==***3==4***C <==記錄輸出時以指定的符號代替原回車換行 aa==bb***
  • NF:字段數量

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    $awk -F: '{print NF}' /etc/passwd 7 <==統計字段數量 $awk -F: '{print $(NF-6)}' /etc/passwd named <==顯示第一列內容,至關於$1,要用括號括起來
  • NR:記錄號

  •  
     
     
     
     
    • 1
    • 2
    $awk -F: '{print NR,$1}' /etc/passwd 45 named <==至關於多了個行號
  • FNR:各文件分別計數,記錄號

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    $awk -F: '{print NR,$1}' /etc/passwd /etc/group 121 named <==一共有多少記錄 處理多個文件時,使用NR會將記錄號累計,不會按文件分開,這時須要使用FNR $awk -F: '{print FNR,$1}' /etc/passwd /etc/group 45 named <==/etc/passwd文件最後一個記錄 76 named <==/etc/group文件最後一個記錄
  • FILENAME:當前文件名
    承上例,若是以爲顯示不清楚,能夠加上文件名

  •  
     
     
     
     
    • 1
    • 2
    $awk -F: '{print FNR,FILENAME,$1}' /etc/passwd /etc/group 76 /etc/group named
  • ARGC:命令行參數的個數

  •  
     
     
     
     
    • 1
    • 2
    $awk '{print ARGC}' /etc/passwd /etc/group 3 <==統計命令行參數的個數
  • ARGV:數組,保存的是命令行所給定的各參數
    上例爲何是3個參數?使用ARGV查看各參數

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    $awk '{print ARGV[0] }' /etc/passwd /etc/group awk <==將awk算爲了一個參數 $awk '{print ARGV[2] }' /etc/passwd /etc/group /etc/group <==第三個參數

    3.2 自定義變量(區分字符大小寫)

    • 格式
      1. -v var=value 例如 -v NAME=USERNAME
      2. 直接在程序中定義變量{NAME=USERNAME;print…}
    • 示例

    1. 示例:使用格式1自定義

    $awk -F: -v USER=「username」 -v UID=「userid」 ‘{print USER":"$1,UID":"$3}’ /etc/passwd  /etc/group
    username:named userid:25 這樣顯示不是很清晰,還記得記錄分隔符嗎
    $awk -F: -v USER=「username」 -v UID=「userid」 -v ORS="\n------\n" ‘{print USER":"$1"\n"UID":"$3}’ /etc/passwd /etc/group

    username:screen
    userid:84

    username:named
    userid:25

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

  • 示例:使用格式2自定義

  •  
     
     
     
     
    • 1
    $awk -F: -v ORS="\n------\n" '{USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3}' /etc/passwd /etc/group
  • 示例:將action放入文件,使用-f選項

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 將程序內容放入文件awk2.txt 中 $cat awk2.txt {USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3} 2. 執行如下命令,寫入文件的程序就不須要單引號了 $awk -F: -v ORS="\n------\n" -f awk2.txt /etc/passwd

    4. action中的printf命令

    • 格式
      printf 「FORMAT」, item1, item2, …
    • 注意事項

    • 必須指定FORMAT
    • 不會自動換行,須要顯式給出換行控制符,\n
    • FORMAT中須要分別爲後面每一個item指定格式符
  • 格式符:與item對應

  • 符號 釋義
    %c 顯示字符的ASCII碼
    %d, %i 顯示十進制整數
    %c 顯示字符的ASCII碼
    %e, %E 顯示科學計數法數值
    %g, %G 以科學計數法或浮點形式顯示數值
    %s 顯示字符串
    %u 無符號整數
    %% 顯示%自身
    • 修飾符

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

  • 示例1: 取出/etc/passwd第1,3行,並在其前分別加Username和UID

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

    示例2:%s對應$1,表示文件第一行爲字符串,在%與s中間能夠添加參數[-]表示左對齊[20]表示第一列所佔寬度,同理%-4d表示$2佔4個字符寬度左對齊

     
     
     
     
     
    • 1
    • 2
    • 3
    $awk -F: '{printf"|%-20s %-4d|\n---------------------------\n",$1,$3 }' /etc/passwd |named 25 | ---------------------------

    示例3:在這裏演示一下BEGIN的效果,添加表頭,效果以下

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    $awk -F: 'BEGIN{print "|user |ID |\n----------------------------"}''{printf"|%-20s |%-4d|\n----------------------------\n",$1,$3 }' /etc/passwd |user |ID | <==頭部,BEGIN所述內容 ---------------------------- |root |0 | <==文件內容,printf所述內容 ----------------------------

    示例4:小數處理示例

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1$echo "3.1415 1.15926" |awk '{printf "%2.2f;%1.4f",$1,$2}' 3.14;1.1593 %2.2f第一個2表示寬度,第二個2個小數點保留位數 %1.4f最後一位達到6時會進位 2$echo "3.1415 1.15925" |awk '{printf "%2.2f;%1.4f",$1,$2}' 3.14;1.1592 %1.4f最後一位值爲5時不會進位 3$echo "3.1415 11.15925" |awk '{printf "%2.2f;%10.4f",$1,$2}' 3.14;***11.1593 <==這裏爲了顯示效果,以***代替空格,共10個寬度 %10.4f寬度起做用了,說明寬度若是小於實際佔用值,會以實際寬度爲準

    5. 操做符

    5.1 算術操做符:

    操做符 定義
    +
    -
    *
    /
    % 取餘
    ^
    -x 轉換爲負數
    +x 轉換爲數值

    5.2 賦值操做符:

    操做符 定義
    = 賦值
    += 將加的結果賦給變量
    -= 將減的結果賦給變量
    *= 將乘的結果賦給變量
    /= 將除的結果賦給變量
    %= 將取餘的結果賦給變量
    ^= 將取冪的結果賦給變量
    ++ 變量加1
    變量減1

    • 示例:下面兩語句有何不一樣
      awk ‘BEGIN{i=0;print ++i,i}’
      awk ‘BEGIN{i=0;print i++,i}’
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@hai7 ~]$awk 'BEGIN{i=10;print ++i,i}' 11 11 先遞增,再將遞增值打印 [root@hai7 ~]$awk 'BEGIN{i=10;print i++,i}' 10 11 先打印i值,再遞增

    5.4 比較操做符:

    操做符 定義
    == 等於
    != 不等於
    > 大於
    >= 大於等於
    < 小於
    <= 小於等於

    5.5 模式匹配符

    操做符 定義
    ~ 左邊是否和右邊匹配
    !~ 是否不匹配

    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1:篩選文件/etc/passwd中包含root的行 [root@hai7 ~]$awk -F: '$0 ~ /root/{print NR$1}' /etc/passwd 1 root 10 operator 2:篩選文件/etc/passwd中以root開頭的行 [root@hai7 ~]$awk -F: '$0 ~ "^root"{print NR,$1}' /etc/passwd 1 root 3:篩選文件/etc/passwd中不包含root的行 [root@hai7 ~]$awk -F: '$0 !~ /root/{print NR,$1}' /etc/passwd 2 bin 9 mail 11 games 4:篩選第三字段爲0的行 [root@hai7 ~]$awk -F: '$3==0' /etc/passwd root:x:0:0:root:/root:/bin/bash

    5.6 邏輯操做符:與&&,或||,非!

    操做符 定義
    && 邏輯與
    邏輯非

    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1:篩選第3個字段大於等於50而且小於等於60的行 [root@hai7 ~]$awk -F: '$3>=50 && $3<=60 {print NR,$1}' /etc/passwd 31 tss 2:篩選第3個字段等於0或大於等於1000的行 [root@hai7 ~]$awk -F: '$3==0 || $3>=1000 {print NR,$1}' /etc/passwd 1 root 29 nfsnobody 43 dong 3:篩選第3個字段小於等於1000之外的行 $awk -F: '!($3<=1000) {print NR,$1}' /etc/passwd 29 nfsnobody
    • 條件表達式(三目表達式):
      (selector1)?if-true(expression2):if-false(expression)
      先求表達式selector1的值,若是爲真,則執行表達式2,並返回表達式2的結果;若是表達式1的值爲假,則執行表達式3,並返回表達式3的結果。

    • 示例:
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    先定義條件第3字段大於等於1000,若是成立則打印type="user",不成立打印type="sys" [root@hai7 ~]$awk -F: '{$3>=1000?type="user":type="sys";printf"%+15s %s\n" ,$1,type}' /etc/passwd root sys nfsnobody user

    6 awk-PATTERN

    • PATTERN:根據pattern條件,過濾匹配的行,再作處理

    1. 若是未指定:空模式,匹配每一行
    2. /regular expression/:僅處理可以模式匹配到的行,須要用/ /括起來

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    例1:判斷磁盤利用率,取出設備行 $df|awk -F " +|%" '/^\/dev\/sd/{print $1,$5}' /dev/sda2 11 /dev/sda3 1 /dev/sda1 16 例2:統計磁盤文件系統類型 $awk -F" +" '/^UUID/{print $3}' /etc/fstab|sort|uniq -c 2 swap 3 xfs
  • relational expression: 關係表達式,結果爲「真」纔會被處理

    • 真:結果爲非0值,非空字符串
    • 假:結果爲空字符串或0值
    • 示例

    1. 空格或者非0數值,返回值爲非空,結果都爲真,能夠打印結果
      awk -F: '" "{print $1}' /etc/passwd
      awk -F: '1{print $1}' /etc/passwd
      awk ‘!0’ /etc/passwd
    2. 空值或者0,返回值爲空,結果爲假,不作處理
      awk -F: ' ""{print $1} ' /etc/passwd
      awk -F: '0{print $1}' /etc/passwd
      awk ‘!12345’ /etc/passwd 任何非0值取反都爲空
    3. 下例分爲兩條命令

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@hai7 ~]$awk -F: 'i=1;j=1{print i,j}' /etc/passwd named:x:25:25:Named:/var/named:/sbin/nologin 1 1 i=1;j=1{print i,j}是兩條命令 i=1省略了{print ...}因此默認打印$0 seq 10 |awk ‘i=0’
  • 取偶數行或奇數行
    打印奇數行,由於i沒有指定值因此爲空,第一次執行時爲空=!空,因此打印1,第二次執行時,非空=!非空值爲0,因此不處理,以此類推,能夠經過seq 10 | awk '{i=!i;print i}'查看返回結果
    • seq 10 |awk 'i=1'打印全部數字
    • seq 10 | awk 'i=!i'打印奇數行
    • seq 10 | awk '!(i=!i)'打印偶數行
    • seq 10 |awk -v i=1 'i=!i'打印偶數行
  • line ranges:行範圍

    • 利用正則表達式寫法取範圍
      startline,endline:/pat1/,/pat2/ 不支持直接給出數字格式
      awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd

    • 先要處理指定的行範圍,能夠利用NR記錄編號來實現
      awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd

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

    • 示例

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    示例1: [root@hai7 ~]$awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd USER USERID <==BEGIN的內容 root:0 apache:48 named:25 end file <==END的內容 示例2: $awk -F: '{print "USER USERID";print $1":"$3} END{print "end file"}' /etc/passwd USER USERI <==不是開始處理的文本,會被循環打印 root:0 USER USERI bin:1

    7. awk action

    7.1awk控制語句if-else

    • 語法
      if(condition){statement;…}[else statement]
      if(condition1){statement1}else if(condition2){statement2}else{statement3}
    • 使用場景:對awk取得的整行或某個字段作條件判斷
    • 示例:

    示例1:取出第3字段大於等於1000的行

     
     
     
     
     
    • 1
    • 2
    • 3
    awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd awk -F: '$3>=1000{print $1,$3}' /etc/passwd 效果相同,格式不一樣控制語句是action裏的要寫在花括號內,判斷語句是屬於patter的要寫在花括號外面

    示例2:取磁盤利用率高於5%的

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    $df|awk -F" +|%" '/^\/dev\/sd/{if($5>5){print $1,$5;print "it is full"}}' /dev/sda2 11 it is full /dev/sda1 16 it is full

    示例3:取訪問日誌中IP地址重複次數超過100的,放到防火牆中

     
     
     
     
     
    • 1
    • 2
    • 3
    [root@hai7 ~]$ab -c10 -n 100 http://172.20.50.201/ 實驗準備屢次訪問某地址 [root@hai7 ~]$cat /var/log/httpd/access_log|awk -F" " '{print $1}'|uniq -c|awk -F" " '{if($1>100){print $2}'|while read ip;do iptables -A INPUT -s $ip -j REJECT;done [root@hai7 ~]$iptables -F 清空防火牆

    示例3:shell類型使用bash的行

     
     
     
     
     
    • 1
    awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd

    示例4:第3字段大於等於1000的標記爲Common user,不然標記爲root or Sysuser

     
     
     
     
     
    • 1
    • 2
    awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd

    7.2 awk控制語句 while循環

    • 語法:
      while(condition){statement;…}
    • 條件「真」,進入循環;條件「假」,退出循環
    • 使用場景:
      對一行內的多個字段逐一相似處理時使用
      對數組中的各元素逐一處理時使用
    • 示例:

    示例1:用awk寫1..100相加

     
     
     
     
     
    • 1
    • 2
    $awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}' 5050

    示例2:找出無論前面多少空格linux16開頭的行,統計各字段字符串長度

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    [root@hai7 ~]awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg 示例中length是系統函數,用來統計括號中字符串長 [root@hai7 ~]$awk 'BEGIN{print length("sdgdgasdfwergejut")}' 17

    示例3:統計字段字符串長度超過10的

     
     
     
     
     
    • 1
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg

    示例4:判斷隨機數最大值與最小值

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1:生成以逗號爲分隔符的隨機數到文件f1 [root@hai7 ~]$(echo "$RANDOM" ;for((i=1;i<100;i++));do echo -n ",$RANDOM";done)>f1 2: 取出隨機數最大值和最小值 [root@hai7 ~]$awk -F',' '{max=$1;min=$1;i=2;while(i<=NF){if($i>max){max=$i}else if($i<min){min=$i};i++;}}END{print "max="max,"min="min}' f1 max=32377 min=148 3:判斷結果是否正確 [root@hai7 ~]tr ',' '\n' <f1.txt|shot -nr

    7.3 控制語句 do-while循環

    • 語法
      do {statement;…}while(condition)
    • 意義
      不管真假,至少執行一次循環體
    • 示例:

    示例1:1..100相加

     
     
     
     
     
    • 1
    $awk 'BEGIN{sum=0;i=1;do {sum+=i;i++}while(i<=100);print sum}

    示例2:統計linux16行,大於10個字符的字段

     
     
     
     
     
    • 1
    $awk '/^[[:space:]]*linux16/{i=1;do {if(length($i)>=10){print $i,length($i)}; i++}while(i<=NF)}' /etc/grub2.cfg

    7.4 awk控制語句 for循環

    • 語法
      for(expr1;expr2;expr3) {statement;…}
    • 常見用法:
      for(variable assignment;condition;iteration process){for-body}
    • 特殊用法:可以遍歷數組中的元素
      - 語法:for(var in array) {for-body}
    • 示例:

    示例1:統計linux16行,各字段字符長度,

     
     
     
     
     
    • 1
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg

    示例2:從1+到100相加

     
     
     
     
     
    • 1
    awk 'BEGIN{sum=0;for(i=1;i<=100;i++)sum+=i;print sum}'

    7.5 awk控制語句 switch語句

    • 語法:
      swich定義的表達式,是否爲case後的只或者正則表達式,若是是則執行statement1, 若是不匹配則繼續判斷第二個case後的值是否匹配,匹配則執行statement2,都不匹配則執行default後續。

    • 格式
      switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; …; default: statementn}

    7.6 awk控制語句 break、continue及next

    • break [n] 結束整個循環體

     
     
     
     
     
    • 1
    • 2
    • 3
    [root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)break;sum+=i} ;print sum}' 1225 循環到50,就不日後加了
  • continue [n]結束單次循環
  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1:i%2==1意思爲奇數循環,跳過奇數循環,得偶數總和 [root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i} ;print sum}' 2550 2:結束第50次循環,會繼續進行後續循環 [root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)continue;sum+=i} ;print sum}' 5000
    • next:
      提早結束對本行處理而直接進入下一行處理(awk自身循環)
     
     
     
     
     
    • 1
    • 2
    打印 奇數行 awk -F: '{if($3%2!=0)next;print NR,$1,$3}' /etc/passwd

    8. 性能比較

    使用awk、shell、bc計算100000相加,參考所用時間,判斷工做性能
    一、awk for循環

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@hai7 /etc/selinux]$time awk 'BEGIN{sum=0;for(i=1;i<=100000;i++)sum+=i ;print sum}' 5000050000 real 0m0.011s user 0m0.010s sys 0m0.001s

    二、awk while循環

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2. $time awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}' 5050 real 0m0.003s user 0m0.002s sys 0m0.001s

    三、shell for循環

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    $time for((sum=0,i=1;i<=100000;i++));do let sum+=i;done;echo $sum real 0m0.666s user 0m0.666s sys 0m0.000s

    四、shell while循環

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    $time ( sum=0;i=1;while [ $i -le 100000 ] ;do let sum+=i;let i++;done;echo $sum) 5000050000 real 0m1.064s user 0m0.992s sys 0m0.072s

    五、bc計算

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    $time seq -s + 100000|bc 5000050000 real 0m0.041s user 0m0.036s sys 0m0.007s

    9. awk數組

    9.1 awk支持關聯數組

    arr[「key」]=value 鍵值對,每一個鍵後面對應着相應的值, 當按下相應的鍵時, 就會輸出相應的結果

    • 格式
      array[index-expression]
    • index-expression:
      • 可以使用任意字符串;字符串要使用雙引號括起來
      • 若是某數組元素事先不存在,在引用時,awk會自動建立此元素,並將其值初始化爲「空串」
      • 若要遍歷數組中的每一個元素,要使用for循環,格式爲for(var in array) {for-body}
    • 示例

    •awk ‘!arr[0]++dupfile0]++′dupfile去掉重複行,例如文件內容爲cat f2
    abc
    cvb
    abc
    當awk讀入第一行時,arr的下標爲abc,沒有賦值爲空,取反爲非空,因此打印第一行,arr[abc]=1
    讀入第二行是,arr的下標爲cbv,沒有賦值爲空,取反爲非空,因此打印
    讀入第三行時,arr的下標爲abc,值爲1,取反爲空,因此不打印 arr[abc]=2

    去掉重複行還可使用sort -u f2
    •awk ‘{!arr[0]++;print0]++;print0, arr[$0]}’ dupfile

    分別定義數組weekdays的鍵值對爲[「mon」]=」Monday」,[「tue」]=」Tuesday」,經過for來遍歷

     
     
     
     
     
    • 1
    awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'

    統計tcp狀態,NF表明最後一個字段,i表示值,state[i]表示累計結果

     
     
     
     
     
    • 1
    netstat -tan | awk '/^tcp/{state[$NF]++}END{for(i in state) { print i,state[i]}}'

    統計IP訪問次數,f1爲導出的IP訪問日誌格式爲,默認以空格爲分隔符
    172.20.7.53 - - [10/Sep/2018:10:18:53 +0800] 「GET / HTTP/1.0」 403 4961 「-」 「ApacheBench/2.3」

     
     
     
     
     
    • 1
    awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' f1|sort -rn

    分別統計男生女生的平

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    [root@hai7 /data]$cat f2 name grade boyorgirls A 76 G B 98 M C 66 M D 95 G E 86 G F 79 M [root@hai7 /data]$awk '!/^name/{if($3=="M"){score_m+=$2;number_m++}else{score_g+=$2;number_g++}}END{print "avg_m="score_m/number_m"","avg_g="score_g/number_g}' f2 avg_m=81 avg_g=85.6667

    方法二

     
     
     
     
     
    • 1
    • 2
    • 3
    [root@hai7 /data]$awk 'NR!=1{score[$3]+=$2;num[$3]++}END{for(sex in num){print sex":avg="score[sex]/num[sex]}}' f2 G:avg=85.6667 M:avg=81

    9.2 自定義函數

    • 格式:
      function name ( parameter, parameter, … ) {
      statements
      return expression
      }
    • 示例:
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    cat fun.awk function max(v1,v2) { v1>v2?var=v1:var=v2 return var } BEGIN{a=3;b=2;print max(a,b)} awk –f fun.awk 3

    9.3 awk中調用shell命令

    空格是awk中的字符串鏈接符,若是system中須要使用awk中的變量可使用空格分隔,或者說除了awk的變量外其餘一概用」「引用起來。

    • 格式 system(「$var」)
    • 示例
      awk BEGIN'{system("hostname") }'
      awk 'BEGIN{score=100; system("echo your score is " score) }'

    9.4 awk腳本

    將awk程序寫成腳本,直接調用或執行

    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1:將pattern{action statements;..}寫到文本中 [root@hai7 /data]$cat f3 {if($3>=1000)print $1,$3} 2:調用文原本篩選文件 $awk -F: -f f3 /etc/passwd nfsnobody 65534 v9 1000 3:創建awk執行腳本 $cat f3 #!/bin/awk -f <==腳本解釋器與shell不一樣 #this is a awk script {if($3>=1000)print $1,$3} <==pattern{action statements;..} 4:加執行權限 chmod +x f3 5:調用腳原本過濾文本 ./f3 –F: /etc/passwd

    9.4.1 向awk腳本傳遞參數

    • 格式
      awkfile var=value var2=value2… Inputfile
    • 注意事項
      • 在BEGIN過程當中不可用。直到首行輸入完成之後,變量纔可用。
      • 能夠經過-v 參數,讓awk在執行BEGIN以前獲得變量的值。命令行中每個指定的變量都須要一個-v參數
    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1:編輯awk腳本 cat test.awk #!/bin/awk –f {if($3 >=min && $3<=max)print $1,$3} 2:加執行權限 chmod +x test.awk 3:執行腳本,向腳本傳遞變量以下,也可使用-v min=100,每一個變量前都要加-v ./test.awk -F: min=100 max=200 /etc/passwd

    10. awk數值處理

    • rand():
      返回0和1之間一個隨機數,須要配合srand實現,srand是用來生成隨機數的種子
      awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
    • int 取整數
      例:生成隨機1-1之間的小數awk 'BEGIN{srand();print rand()}'
      例:生成0-100之間的數awk 'BEGIN{srand();print int(rand()*100)}'

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

    • sub(r,s,[t])
      對t字符串進行搜索r(支持正則表達式)表示的模式匹配的內容,並將第一個匹配的內容替換爲s
      [root@hai7 /data]$echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
      2008-08:08 08:08:08
    • gsub(r,s,[t])
      對t字符串進行搜索r表示的模式匹配的內容,並所有替換爲s所表示的內容
      [root@hai7 /data]$echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
      2008-08-08 08-08-08
    • split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存至array所表示的數組中,第一個索引值爲1,第二個索引值爲2,…
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    用:作分隔符將2008:08:08 08:009:09分割爲5段,分別存放在下標爲1str[1]=2008str[2]=08... echo "2008:08:08 08:009:09"|awk '{split($0,str,":")}END{for(i in str)print i,str[i]}' 4 009 5 09 1 2008 2 08 3 08 08
    <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7f770a53f2.css" rel="stylesheet">
                </div>
    相關文章
    相關標籤/搜索
    本站公眾號
       歡迎關注本站公眾號,獲取更多信息