awk命令用法


  awk:把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理,是一個強大的文本分析工具,在對數據分析並生成報告時很有優勢。

  awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。

  • 命令格式:
    awk [options] 'program' FILE ...
其中:
    options:
        -F:指明輸入時用到的字段分隔符,默認空白字符;
        -v:指定變量
        -v var=value:自定義變量
    program:
        PATTERN{ ACTION STATEMENTS;...} (語句之間用 ; 分隔)
        PATTERN--模式,這意味着並不是對文件中的每一行進行處理,而是處理那些能夠被模式匹配到的行,不跟模式表示全文;
        ACTION--常見的處理機制是打印,命令有print和printf.
  • 變量
    • 常見內置變量  
  FS:切割時的分隔符,默認為空白字符;
  OFS:切割后輸出時的分隔符,默認為空白字符;
  RS:輸入時的換行符,默認為'\n';
  ORS:輸出時的換行符,默認為'\n';
  NF:字段數量 ( $NF表示最后一個字段);
  NR:行數;
  FNR:分別計算各文件的行數;
  FILENAME:當前文件名;
  ARGC:命令行參數的個數;
  ARGV:數組,保存的是命令行所給定的各參數
示例:
   awk -v FS=: '{print $1}' /etc/passwd (相當於awk -F: "{print $1}" /etc/passwd)
   awk -v FS=: -v OFS=, '{print $1,$2}' /etc/passwd
   awk -v RS=' ' '{print}' /etc/issue
   awk '{print NF}' /etc/fstab (可對比 awk '{print $NF}' /etc/fstab,$NF表示最后一個字段)
   awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue (命令行參數有3個,分別為awk,/etc/fstab,/etc/issue)
   awk 'BEGIN{print ARGV[#]}' /etc/fstab /etc/issue (#表示索引下標)
    • 自定義變量
種方式可自定義變量:
    (1) -v var=value
    (2) 在program中直接定義
示例:
  awk -v test="hello gawk" 'BEGIN{print test}' (相當於awk 'BEGIN{test="hello gawk";print test}')
  • 打印輸出
    • print
    print item1,item2,...
示例:
tail -5 /etc/fstab | awk '{print $2,$4}' ($1..$#:內置變量,表示分隔后的字段)
tail -5 /etc/fstab | awk '{print "hello:",$2,$4}' (注意,{}只能由單引號'' 引起來,不能用雙引號"")
要點:
    (1) 逗號,作為不同字段的分隔符;
    (2) item可以是字符串,數值,當前記錄的字段、變量或awk的表達式;
    (3) 如省略item,相當於print $0(打印所有元素;$0表示所有字段)
    • printf
格式化輸出:printf FORMAT,item1,item2,...
釋義:
(1) FORMAT必須給出;
(2) 不會自動換行,需要顯式給出換行控制符,'\n';
(3) FORMAT中需要分別為后面的每個item指定一個格式化符號;
        格式符:
                %c:顯示字符的ASCII碼;
                %d,%i:顯示十進制整數;
                %e,%E:科學計數法數值顯示;
                %f:顯示為浮點數;
                %g,%G:以科學計數法或浮點形式顯示數值;
                %s:顯示字符串;
                %u:無符號整數;
                %%:顯示%自身
        修飾符:
                #[.#]:第一個數字控制顯示的寬度;第二個#表示小數點后的精度
示例:
  %-3.1f,其中 '-' 表示左對齊;%+5.2d,其中 '+' 會顯示數值的符號
  awk -F: '{printf "Uername:%s, UID:%d\n",$1,$3}' /etc/passwd
  awk -F: '{printf "Uername:%-15s, UID:%d\n",$1,$3}' /etc/passwd
  •  操作符
  算術操作符:x+y,x-y,x*y,x/y,x^y(多少次方),x%y
  賦值操作符:=,+=,-=,*=,/=,%=,^=,++,--
  比較操作符:>,>=,<,<=,!=,==
  模式匹配符:~:是否匹配;!~:是否不匹配
  邏輯操作符:&&,||,!
  函數調用:function_name(argu1,argu2,...)
  條件表達式:selector ? if-true-expression : if-false-expression
示例:
  awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s : %-s\n",$1,usertype}' /etc/passwd
  awk '!/^UUID/{print $0}' /etc/fstab
  awk -F: '$3>1000{print $1,$3}' /etc/passwd
  awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
  • PATTERN
(1) /regular expression/:僅處理被模式匹配到的行;
(2) relational expression:關系表達式,為"真"時處理 ("真":結果是非0值或非空字符串);
(3) line ranges:行范圍 (startline, endline 或 /pat1/, /pat2/);
    注意: 此處行范圍不支持直接給出數字的格式
    示例:
  awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
  awk -F: '/^h/,/^s/{print $1}' /etc/passwd (4) BEGIN/END模式: BEGIN{}: 僅在開始處理文件中的文本之前執行一次; END{}:僅在文本處理完成之后執行一次 示例:
  head /etc/passwd | awk -F: 'BEGIN{print "username uid"}{printf "%-12s%-5s\n",$1,$3}END{printf "%10s\n","END"}'
  • 控制語句
    • if-else
語法:
    if(condition) statement [else statement]
使用場景:
    對awk取得的整行或某個字段做條件判斷.
示例:
    awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
    awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
    awk '{if(NF>5) print $0}' /etc/fstab
    df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
    • while and do while
語法:
    while(condition) statement (條件"真"時進入循環;條件"假"時退出循環)
    do statement while(condition) (至少執行一次循環體)
使用場景:
    對一行內的多個字段逐一處理時使用;對數組中的各元素逐一處理時使用.
示例:
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
    • for
語法:
    for(expr1;expr2;expr3) statement
    for(variable assignment;condition;iteration process) {for-body}
示例:
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
特殊用法:遍歷數組中的元素
    語法:for(var in array) {for-body}
    • switch
語法:
    switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
    • break and continue
break:終止循環
continue:中斷本次循環繼續下一輪
    • next
提前結束對本行的處理而直接進入下一行;
示例:
    awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
  • array數組
1) 關聯數組:
    array[index-expression]
    index-expression:
        ① 可使用任意字符串;字符串要使用雙引號;
        ② 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,並將其值初始化為"空串"
2) 若要判斷數組中是否存在某元素,要使用"index in array"格式進行;
3) 若要遍歷數組中的每個元素,要使用for循環:for(var in array) {for-body}
示例:
    awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
    netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){ print i,state[i]}}'
    awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log
    awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab
    awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab
    netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
  • 內置函數
    rand():返回0和1之間一個隨機數;
    length([s]):返回指定字符串的長度;
    sub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,並將其第一次出現替換為s所表示的內容;
    gsub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,並將其所有出現均替換為s所表示的內容;
    split(s,a,[r]):以r為分隔符切割字符s,並將切割后的結果保存至a所表示的數組中
示例:
    netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
    awk '/^[[:space:]]*kernel/{i=1;while(i<=NF){if(length($i)>=7)print $i,length($i);i++}}' /etc/grub.conf


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM