awk簡單使用


AWK —— 三個作者的姓的首字母


awk很強大,是編程語言。

流編輯器、非交互式的文本編輯器、報告生成工具(對文本進行排版,數據彙總)


awk的版本

awk       gawk      nawk

舊版的   GNU awk   新版awk(Solaris)

   # ll /usr/bin/awk 

lrwxrwxrwx. 1 root root 14 May 23 17:03 /usr/bin/awk -> ../../bin/gawk

   # ll /usr/bin/gawk 

lrwxrwxrwx. 1 root root 14 May 23 17:03 /usr/bin/gawk -> ../../bin/gawk

   # ll /bin/gawk 

-rwxr-xr-x 1 root root 382456 Jul  4  2012 /bin/gawk

     在我們的系統裏,awk和gawk一樣


工作模式:

   1、行工作模式,每次讀入一行,存到"$0"裏

   2、使用內置變量FS(區域分隔符,默認是空白)分隔這行,存到$1-$100

   3、輸出時使用內置變量OFS(輸出字段分隔符,默認也是空白)

   4、繼續處理下一行


  假設this is a test  這樣的行

      $0:this is a test

      $1: this

      $2: is

      $3: a

      $4: test

   最多就到$100



一、awk的語法

  awk [選項] '/正則表達式/{處理動作1;處理動作2;...;處理動作n}' 文件列表


二、例子

  打印員工名字和生日

    # awk '{print $1,$4}' employees

 

  打印/etc/passwd文件的用戶名和GID

    # awk -F: '{print $1,$4}' /etc/passwd

三、基本操作

  1、設定分隔符

     -F:指定分隔符

         分隔符可以是字母、符號、數字和"空"

    可以同時指定多個分隔符

    默認是空白(空格或者tab)

     1)單個字符做分隔符

# awk -F: '{print $1}' awk.pass

     2)複合分隔符,多個字符組成的分隔符

# awk -F ":/" '{print $1,$2}' awk.pass

     3)同時指定多個分隔符

 # awk -F "[:/]" '{print $1,$7}' awk.pass

  2、awk的輸出

     1)print

  打印的內容可以是文件的內容,也可以是和文件不相關的內容

        # awk '{print "hello"}' awk.pass

        \n:換行符

          在每一行下面添加空行

           # awk '{print $0"\n"}' awk.pass

        # awk -F: '{print "user:"$1}' awk.pass  //字符串輸出要加雙引號

   \t:製表符,tab

  # awk -F: '{print $1"\t"$2}' awk.pass

           # awk -F: '/root/{print $1,$3}' awk.pass 

        練習:

  ifconfig和awk結合,取出eth0的IP地址

   # ifconfig eth0 | awk -F"[: ]" '/Bcast/{print $13}'

     # ifconfig eth0| awk -F: '/Bcast/{print $2}' | awk '{print $1}'



       2)printf  —— 可以格式化輸出,默認不輸出換行符

   printf format,item1,item2,...,itemn

   format:指示符都以%開頭,後面一個字符:

    %s:表示字符串  string

    %d:表示十進制整數,沒有四捨五入,直接取整

    %f:表示浮點數,即小數,默認小數點後保留六位,會四捨五入

    %%: 表示%本身

    %o: 八進制數

    %x: 十六進制數

    %c:  字符

 修飾符:

N(數字),指定顯示寬度   %2s 

  注意:寬度>=字段的最長的長度

-:表示左對齊(默認是右對齊)   %-2s

+: 顯示數值符號

# echo "12.35 11.2345 34.56" > awkf1

# awk '{printf "%d",$1}' awkf1   

# awk '{printf "%d\n",$1}' awkf1

# awk '{printf "%f\n",$1}' awkf1 

   12.350000

# awk '{printf "%.1f\n",$1}' awkf1 

    12.3

# awk '{printf "%5.2f\n",$2}' awkf1 

   5.2表示顯示寬度是5,即整數位和小數位的總顯示長度爲5;2表示保留兩位小數

   \n:換行符

printf與print的區別:

1)printf需要指定格式

2)printf默認不換行

3)printf默認沒有輸出分隔符

默認輸出時,右對齊

# awk -F: '{printf "%10s %d\n",$1,$3}' awk.pass

左對齊

# awk -F: '{printf "%-10s %d\n",$1,$3}' awk.pass

 

 練習:

        /etc/passwd文件,讓你格式化輸出用戶名,UID,GID三列

  #  awk -F: '{printf "%-13s\t%d\t%d\n",$1,$3,$4}' /etc/passwd

  # awk -F: '{printf "%-15s %-10d %-10d \n",$1,$3,$4}'  /etc/passwd

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

  3、awk的操作符

     1)算數運算符

   + - * / 

  %    取餘  5%3 = 2

        x^y x**y   x的y次方,x的y次冪   2^5 = 32

     # awk '{print $3+$5}' employees

     # awk '{print $3-$5}' employees

     # awk '{print $3*$5}' employees

     # awk '{print $5/$3}' employees

     # awk '{print $5%$3}' employees

     2)關係運算符

(1)數值之間的關係

    >   <   >=  <=  !=  ==

   $3 == 0

   $1 == "root"

(2)字符串之間的關係

   x ~ /y/   —— 匹配正則

   x !~ /y/  —— 不匹配

打印uid大於3的用戶名和uid

   # awk -F: '$3 > 3 {print $1,$3}' awk.pass

用戶名包含a的,輸出其名字

   # awk -F: '$1 ~ /a/ {print $1}' awk.pass

     3)邏輯運算符

&&   ||    !

打印uid大於等於3,並且用戶名中含有p的用戶名和家目錄

# awk -F: '$3 >= 3 && $1 ~ /p/ {print $1,$6}' /etc/passwd

打印用戶名中不含p的行

# awk -F: '!($1 ~ /p/){print}' awk.pass

   練習:/etc/passwd

1、打印GID在20和30之間的用戶名和登錄shell

  # awk -F : '$4 >= 20 && $4 <= 30 {print $1,$7}' /etc/passwd

2、打印uid和gid不相等的用戶名、uid和gid

  # awk -F:  '$3!=$4  {print $1,$3,$4 }' /etc/passwd

3、將uid和用戶名互換位置輸出,其他位置原樣輸出

  # awk -F: '{print $3,$2,$1,$4,$5,$6,$7}' /etc/passwd

4、打印shell爲非登錄shell的用戶名

  # awk -F :  '!($7 ~ /sh/) {print $1}' /etc/passwd

  # awk -F: '$7 !~ /sh/{print $1}' /etc/passwd

5、打印所屬組是bin的用戶名  

  # awk -F: '$4==1 {print $1}' /etc/passwd

6、打印100以內能被7整除的數以及包含7的數(seq 100 生成1-100)

  # seq 100 | awk   '$1~/7/ || $1%7==0{print}'

 -----------------------------------------------------------------


    4)賦值運算符

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

4、定址(模式匹配)——awk+正則表達式

   常見的模式:

     1)沒有模式,每一行都處理

# awk -F: '{print $1}' awk.pass

     2)有一個模式,處理匹配到模式的行

   # awk -F: '/^root/{print $1}' awk.pass

     3)範圍定址   //,//   注意:不能使用行號定址

        # awk -F: '/^r/,/^d/{print $1}' awk.pass

        範圍定址仍然是最小匹配


5、awk的變量

   內部變量、自定義變量

   1)內部變量

      (1)$0    表示一整行內容

           # awk -F: '/root/{print $0}' awk.pass 

  # awk -F: '/root/{print}' awk.pass 

  # awk -F: '/root/' awk.pass

      (2)$1 -  $100

    $1: 第一列

    $2:第二列

  ......

  $100:第100列

      (3)與記錄相關的變量   記錄=行

  FS:Field Separator 字段分隔符,默認是空白;其實是讀取文本時,使用的字段分隔符   FS=":"

  RS:Record Separator 記錄分隔符,即行的分隔符,默認是換行符;其實就是讀取文本時,使用的行分隔符  RS="/"

  OFS:Output Field Separator 輸出字段分隔符

  ORS:Output Record Separator 輸出記錄分隔符

       (4)與數據相關的變量

      NR:記錄數  awk處理的記錄的總數,可以表示行號

           NF:字段數  當前記錄的字段數

$NF:當前行最後一個字段的值

$(NF-1):當前行的倒數第二個字段 

    打印/etc/passwd的第二行

# awk 'NR==2 {print}' /etc/passwd

    打印偶數行

awk 'NR%2==0 {print}' /etc/passwd

    打印/etc/passwd同時顯示行號

# awk '{print NR,$0}' /etc/passwd

  # awk -F: '{print NR": "NF}' awk.pass

  # awk -F: '{print NR": "NF,$(NF-1)}' awk.pass

練習:

  通過mount命令,查看所有分區是否可讀可寫,輸出結果爲:

      /dev/sda2   rw

      wp:# mount | awk -F "[ ()]" '/^\//{print $1,$7}'

   2)自定義變量

用戶根據自己需求去定義的變量

變量的命名規則:只能使用字母、數字、下劃線,並且不能以數字開頭,在awk中變量名是區分大小寫的

      合法的:a1  a  abcd  ab_123   

     不合法的:1a   1_a

什麼是變量?

  保存值的。在awk中變量可以先定義再使用,也可以直接就用。

說明:如果沒有對變量進行定義沒有初始值,如果變量被認爲是字符串,它的值就是空"";如果字符串被認爲是數值,那麼它的值就是0。

給變量賦值:var=value

  變量名=數字

  變量名="字符串"

# awk '{a="qwe";print a}' awk.pass

     練習:

        自己定義兩個變量,一個數值型,一個字符串型,使用printf打印它們

# awk '{a="Hello";b=100;printf"%s\t%d\n",a,b}' awk.pass

# awk '{a="hello";b=250;printf "%s %d\n",a,b}' awk.pass

    賦值運算:

      = += ......

      a=5

      a+=5    a=a+5

a-=5    a=a-5

a*=5    a=a*5

    a++  a--    //先使用,後運算

    ++a  --a    //先運算,再使用

    自增 自減     

       # awk '{a=5;b=a++;print a,b}' test

  6 5

       # awk '{a=5;b=a;a=a+1;print a,b}' test

  6 5

       # awk '{a=5;b=++a;print a,b}' a

  6 6

       # awk '{a=5;a=a+1;b=a;print a,b}' test

  6 6

       自己練習:

           --a

# awk '{a=5;b=--a;print a,b}' test

  4 4

    # awk '{a=5;a=a-1;b=a;print a,b}' test

  4 4

6、awk中的重定向   瞭解

   >    >>

   # awk -F: '$3 > 2 {print $1,$3 > "/tmp/pass"} ' awk.pass 

   # cat /tmp/pass 

adm 3

lp 4

   # awk -F: '$3 > 2 {print $1,$3 >> "/tmp/pass"} ' awk.pass 

   # cat /tmp/pass 

adm 3

lp 4

adm 3

lp 4

   # awk -F: '$3 > 2 {print $1,$3 } ' awk.pass  >> /tmp/pass

7、管道   瞭解

   # awk -F: '{print $1,$3 | "sort -nr -k2"}' awk.pass

     默認管道是不會關閉的,所以在腳本真正使用時候是需要關閉的


8、awk的特殊模式  BEGIN  END

   '

   BEGIN{動作}  //在處理文件之前執行的,並且只執行一次 

   /定址/{動作} //有可能會執行多次

   END{動作}    //在處理文件之後執行的,並且只執行一次

   '

  BEGIN:一般定義變量,初始化分隔符,定義數組,打印表頭等等

  END:一般END數據彙總,打印結尾


   注意:BEGIN和END可以單獨存在


   # awk 'BEGIN{FS=":"}{print $1,$2}END{print "over"}' awk.pass 

root x

bin x

daemon x

adm x

lp x

over

  # awk 'BEGIN{print "class is not over"}'  //只有BEGIN的時候,後面可以沒有文件

class is not over

 

  END:後面必須接文件,並且這個文件要麼爲空文件,要麼爲已存在的文件

  # awk 'END{print "class is not over"}' awk.pass 

class is not over

  # touch abc

  # awk 'END{print "class is not over"}' abc

class is not over

  # awk 'BEGIN{sum=0}{sum+=$3;print $1,$3}END{print "sum: "sum}' employees

Tom 4424

Mary 5346

Sally 1654

Billy 1683

sum: 13107


  練習:統計/etc目錄下所有普通文件總大小

# ll /etc/ | awk '/^-/{sum+=$5}END{print sum}'

# ll /etc/ | awk 'BEGIN{sum=0}/^-/{sum+=$5}END{print sum}'


9、awk腳本

   打印datafile文件的第一個字段和倒數第二個字段,對最後一個字段求和並打印

   # cat sc.awk 

BEGIN{      //注意:大括號一定要跟BEGIN同行

     print "Class is over.That is not true."

}

{

     printf "%-10s %d\n",$1,$(NF-1);sum+=$NF

}

END {

     printf "sum:%10.2f\n",sum

}



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