文本處理工具-awk

文本處理工具awk

awk的名字由來:創始人Aho, Weinberger, Kernighan三人的首字母

有多種版本:New awk(nawk),GNU awk(gawk)

 .gawk   模式掃描和處理語言

  基本用法:

awk [options] ‘program’ var=value file…

awk [options] -f programfile var=value file…

awk [options] 'BEGIN{ action;… } pattern{ action;… } END{

action;… }' file …

注:awk 程序通常 由:BEGIN 語句 塊、能夠使用模式匹配的通用語句塊、END 語句塊,共3 部分 組成program 通常是被單引號或雙引號中

選項:

-F 指明輸入時用到的字段分隔符

-v var=value: 自定義變量

-f scrifile :調用awk命令

基本格式:

awk [options] 'program' file…

program:pattern{action statements;..}

pattern 和action: :

? pattern 部分決定動作語句何時觸發及觸發事件(BEGIN,END)

? action statements對 對 數據進行處理,放在{} 內指明(print, printf)

分割符、域和記錄

? awk 執行時,由分隔符分隔的字段(域)標記$1,$2..$n稱為域標識。$0為所有域。

注意:和shell中變量$符含義不同

? 文件的每一行稱為記錄

? 省略action行,則默認執行print $0的操作

 print 格式:print item1, item2, …

  要點 :

? (1) 逗號分隔符

? (2) 輸出的各item 可以字符串,也可以是數值;當前記錄的字段 、變量或awk的表達式

? (3) 如省略item ,相當于print $0

1:打印hello awk 用/etc/issue的行

[root@lxc ~]# awk '{print "hello awk"}' /etc/issue

hello awk

hello awk

hello awk

[root@lxc ~]#

2:顯示系統中所有的用戶名和UID

[root@lxc ~]# awk -F: '{print $1 "\t" $3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3

lp 4

sync 5

……

.awk變量

變量:內置和自定義變量

 FS:輸入字段分隔符,默認為空白字符

例:

[root@lxc ~]# awk -v FS=":" '{print $1,FS,$3}' /etc/passwd

root : 0

bin : 1

daemon : 2

adm : 3

lp : 4

sync : 5

……

 OFS:輸出字段分隔符,默認為空白字符

例:

[root@lxc ~]# awk -v FS=":" -v OFS="====" '{print $1,$3}' /etc/passwd

root====0

bin====1

daemon====2

adm====3

lp====4

sync====5

shutdown====6

……

 RS :輸入記錄分隔符,指定輸入時的換行符原換行符仍有效

例:

[root@lxc ~]# cat test.txt

a b c

dd ee ff

gg

[root@lxc ~]# awk -v RS=" " '{print $1}' test.txt

a

b

c

ee

ff

[root@lxc ~]#

 ORS :輸出記錄分隔符,輸出時用指定符號代替換行符

例:

[root@lxc ~]# awk -v RS=" " -v ORS="=" '{print $1}' test.txt

a=b=c=ee=ff=[root@lxc ~]# cat test.txt

a b c

dd ee ff

gg

[root@lxc ~]#

 NF :字段數量

1:打印字段數量

[root@lxc ~]# awk -F: '{print NF}' /etc/passwd

7

7

7

7

7

……

2:顯示最后一個字段

[root@lxc ~]# awk -F: '{print $NF}' /etc/passwd

/bin/bash

/sbin/nologin

/sbin/nologin

/sbin/nologin

/sbin/nologin

 ……

 NR :行號

例:

[root@lxc ~]# awk -F: '{print NR}' /etc/passwd

1

2

3

4

5

6

……

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

例:

[root@lxc ~]# awk '{print FNR}' test.txt /etc/issue

1

2

3

1

2

3

[root@lxc ~]#

 FILENAME :當前文件名

例:

[root@lxc ~]# awk -F: '{print FNR,FILENAME,$1}' /etc/issue test.txt

1 /etc/issue CentOS release 6.8 (Final)

2 /etc/issue Kernel \r on an \m

3 /etc/issue

1 test.txt a b c

2 test.txt dd ee ff

3 test.txt gg

[root@lxc ~]#

 ARGC :命令行參數的個數

[root@lxc ~]# awk '{print ARGC}' /etc/fstab /etc/inittab

3

3

3

……

 ARGV :數組,保存的是命令行所給定的各參數(不理解)

例:

[root@lxc ~]# awk 'BEGIN {print ARGV[0]}' /etc/fstab

awk

[root@lxc ~]#

自定義變量

(1) -v var=value 變量名區分字符大小寫

(2) 在program中直接定義

1:

[root@lxc ~]# awk -F: -v name="username" -v uid="uid" '{print name":"$1,"\t"uid":"$3}' /etc/passwd

username:root uid:0

username:bin uid:1

username:daemon uid:2

username:adm uid:3

username:lp uid:4

……

2:

[root@lxc ~]# awk -F: '{n="haha";m="xixi";print n,m}' /etc/passwd

haha xixi

haha xixi

haha xixi

haha xixi

haha xixi

……

.printf命令

  格式化輸出:printf “FORMAT ”, item1, item2, …

    (1) 必須指定FORMAT

    (2) 不會自動換行,需要顯式給出換行控制符,\n

    (3) FORMAT 中需要分別為后面每個item 指定格式符

   格式符:與item 一一對應

      %c: 顯示字符的ASCII碼 碼

      %d, %i: 顯示十進制整數

      %e, %E: 顯示科學計數法數值

      %f :顯示為浮點數

      %g, %G :以科學計數法或浮點形式顯示數值

      %s :顯示字符串

      %u :無符號整數

      %%:  顯示%自身

  修飾符:

      #[.#] :第一個數字控制顯示的寬度;第二個# 表示小數點后精度,%3.1f

      -:  左對齊(默認) 右對齊) %-15s

      + :顯示數值的號 正負符號 %+d

1:

[root@lxc ~]# awk -F: '{printf "%s %d\n",$1,$3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3

lp 4

sync 5

……

2:

[root@lxc ~]# awk -F: '{printf "%s\n",$1}' /etc/passwd

root

bin

daemon

adm

lp

……

3:

[root@lxc ~]# awk -F: '{printf "username: %s\n",$1}' /etc/passwd

username: root

username: bin

username: daemon

……

4:

[root@lxc ~]# awk -F: '{printf "username: %15s,uid:%d\n",$1,$3}' /etc/passwd

username:            root,uid:0

username:             bin,uid:1

username:          daemon,uid:2

username:             adm,uid:3

username:              lp,uid:4

……

5:

[root@lxc ~]# awk -F: '{printf "username: %-15s,uid:%d\n",$1,$3}' /etc/passwd

username: root           ,uid:0

username: bin            ,uid:1

username: daemon         ,uid:2

username: adm            ,uid:3

username: lp             ,uid:4

username: sync           ,uid:5

……

.操作符

  算術操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x:  轉換為負數

+x:  轉換為數值

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

   賦值操作符:=, +=, -=, *=, /=, %=, ^=,++, —

例:

[root@lxc ~]# awk 'BEGIN{n=1;m=2;print m+=n}'

3

[root@lxc ~]#

   比較操作符:>, >=, <, <=, !=, ==

例:

[root@lxc ~]# awk -F: '$3 > 1000 {print $1,$3}' /etc/passwd

nfsnobody 65534

[root@lxc ~]#

 

  模式匹配符:

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

!~ :是否不匹配

例:

[root@lxc ~]# awk '$0 !~ /root/' /etc/passwd

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

……

 

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

例:

[root@lxc ~]# awk -F: '!($3==0 || $3 >=1000){print $1,$3}' /etc/passwd

bin 1

daemon 2

adm 3

lp 4

sync 5

shutdown 6

……

 

函數調用:function_name(argu1, argu2, …)

條件表達式(三目表達式):

selector?if-true-expression:if-false-expression

例:

[root@lxc ~]# awk -F: '{$3>=1000?usertype="Commom user":usertype="susadmin sysuser";printf"%15s:%-s\n",$1,usertype}' /etc/passwd

           root:susadmin sysuser

            bin:susadmin sysuser

         daemon:susadmin sysuser

            adm:susadmin sysuser

             lp:susadmin sysuser

           sync:susadmin sysuser

       shutdown:susadmin sysuser

……

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

(1) 如果未指定:空模式,匹配每一行

(2) /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來

(3) relational expression: 關系表達式,結果有“真”有“假”,結果為“真”才會被處理。

真:結果為非0值,非空字符串

假:結果為空字符串或0值

1:結果為假不處理

 

[root@lxc ~]# awk '"" {print $0}' /etc/fstab

[root@lxc ~]#

2:結果為真處理

[root@lxc ~]# awk '1{print $0}' /etc/fstab

 

#

# /etc/fstab

# Created by anaconda on Thu Nov  3 19:08:05 2016

#

# Accessible filesystems, by reference, are maintained under '/dev/disk'

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info

……

3:

[root@lxc ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd

root /bin/bash

lxc /bin/bash

[root@lxc ~]#

4:

[root@lxc ~]# awk -F: '$NF!~"/bin/bash"{print $1,$NF}' /etc/passwd“

bin /sbin/nologin

daemon /sbin/nologin

adm /sbin/nologin

lp /sbin/nologin

sync /bin/sync

shutdown /sbin/shutdown

……

(4) line ranges:行范圍

startline,endline :/pat1/,/pat2/  不支持直接給出數字格式

1:

[root@lxc ~]# awk -F: '/^root/,/^lp/' /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

[root@lxc ~]#

2:

[root@lxc ~]# awk -F: 'NR>=10 && NR<=15 {print NR,$0}' /etc/passwd

10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

11 operator:x:11:0:operator:/root:/sbin/nologin

12 games:x:12:100:games:/usr/games:/sbin/nologin

13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

15 nobody:x:99:99:Nobody:/:/sbin/nologin

[root@lxc ~]#

 

(5) BEGIN/END模式

BEGIN{}: 僅在開始處理文件中的文本之前執行一次

END{}:僅在文本處理完成之后執行

1:

[root@lxc ~]# awk -F: 'BEGIN{print "linenumber username"}NR>10&&NR<=15{print NR,$0}' /etc/passwd

linenumber username

11 operator:x:11:0:operator:/root:/sbin/nologin

12 games:x:12:100:games:/usr/games:/sbin/nologin

13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

15 nobody:x:99:99:Nobody:/:/sbin/nologin

[root@lxc ~]#

2:

[root@lxc ~]# awk -F: 'BEGIN{print "linenumber username"}NR>10 && NR<=15{print NR,$0}END{print "end"}' /etc/passwd

linenumber username

11 operator:x:11:0:operator:/root:/sbin/nologin

12 games:x:12:100:games:/usr/games:/sbin/nologin

13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

15 nobody:x:99:99:Nobody:/:/sbin/nologin

end

[root@lxc ~]#

3:

[root@lxc ~]# seq 10 | awk 'i=0'

[root@lxc ~]# seq 10 | awk 'i=1'

1

2

3

4

5

6

7

8

9

10

[root@lxc ~]# seq 10 | awk 'i=!i'

1

3

5

7

9

[root@lxc ~]# seq 10 |awk '{i=!i;print i}'

1

0

1

0

1

0

1

0

1

0

[root@lxc ~]# seq 10 |awk '!(i=!i)'

2

4

6

8

10

[root@lxc ~]# seq 10 |awk -v i=1 'i=!i'

2

4

6

8

10

[root@lxc ~]#

.awk 控制語句

 { statements;… }  組合語句

 if(condition) {statements;…}

 if(condition) {statements;…} else {statements;…}

 while(conditon) {statments;…}

 do {statements;…} while(condition)

 for(expr1;expr2;expr3) {statements;…}

 break

 continue

 delete array[index]

 delete array

 exit

if-else

語法:if(condition) statement [else statement]

if(condition1){statement1}else if(condition2){statement2}

else{statement3}

  使用場景:對awk取得的整行或某個字段做條件判斷

1:顯示普通用戶的用戶名和UID

[root@lxc ~]# awk -F: '{if ($3>=500) print $1,$3}' /etc/passwd

nfsnobody 65534

lxc 500

[root@lxc ~]#

2:顯示磁盤利用率超過80%的

[root@lxc ~]# df -h |awk -F% '/^\/dev/{print $1}'|awk '{if($NF>80)print $1,$5}'

[root@lxc ~]#

3:判斷成績

[root@lxc ~]# awk 'BEGIN{test=100;if(test>90){print "very good"}else if(test>60){prin t good""}else{print "no pass"}}'

very good

[root@lxc ~]#

 while 循環

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

  條件“真”,進入循環;條件“假”, 退出循環

  使用場景:對一行內的多個字段逐一類似處理時使用

       對數組中的各元素逐一處理時使用

例:顯示文件中以linux16為行首(行首可有空格)的行中的各個字段及所字段字符串的長度

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

/vmlinuz-3.10.0-327.el7.x86_64 30

root=/dev/mapper/centos-root 28

crashkernel=auto 16

rd.lvm.lv=centos/root 21

rd.lvm.lv=centos/swap 21

net.ifnames=0 13

/vmlinuz-0-rescue-0dc32f41d52e4e3a9bd9a30a2683ae5d 50

root=/dev/mapper/centos-root 28

crashkernel=auto 16

rd.lvm.lv=centos/root 21

rd.lvm.lv=centos/swap 21

net.ifnames=0 13

[root@localhost ~]#

   do-while 循環

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

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

例:1~100的自然數的和

[root@lxc ~]# awk 'BEGIN{sum=0;i=0;do{sum+=i;i++;}while(i<=100);print sum}'

5050

[root@lxc ~]#

   for 循環

  語法:for(expr1;expr2;expr3) {statement;…}

  常見用法:

for(variable assignment;condition;iteration process)

{for-body}

  特殊用法:能夠遍歷數組中的元素;

  語法:for(var in array) {for-body}

例:1~100的自然數的和

[root@lxc ~]# awk 'BEGIN{total=0;for(i=1;i<=100;i++){total+=i}{print total}}'

5050

[root@lxc ~]#

2:

1~100之間的奇數之和

[root@lxc ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i};print sum}'

2550

[root@lxc ~]#

 switch 語句

  語法: :switch(expression) {case VALUE1 or /REGEXP/:

statement1; case VALUE2 or /REGEXP2/: statement2;

…; default: statementn}

 break 和continue

例:

[root@lxc ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if (i%2==0)break;sum+=i}print sum}'

1

[root@lxc ~]#

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

例:

[root@lxc ~]# awk -F: '{if ($3%2==0)netx;print$1,$3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3

lp 4

……

.awk數組

   關聯數組:array[index-expression]

index-expression:

(1) 可使用任意字符串;字符串要使用雙引號括起來

(2) 如果某數組元素事先不存在,在引用時,awk 會自動創建此元素,并將其值初始化為“空串”

注:若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷

1:

[root@lxc ~]# awk 'BEGIN{arr["frist"]="mage";arr["second"]="laowang";print arr["frist"]}'

mage

[root@lxc ~]#

2:

[root@lxc~]# awk' BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuseday";for(i in weekdays){print weekdays[i]}}'

Monday

Tuseday

[root@lxc ~]#

   數值處理:

   rand():返回0和1之間一個隨機數

[root@lxc ~]# awk 'BEGIN{srand();for (i=1;i<=5;i++)print int(rand()*100)}'

5

17

68

52

49

[root@lxc ~]#

  字符串處理:

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

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

例:

[root@lxc ~]# echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'

2008-08:08 08:08:08

[root@lxc ~]#

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

s所表示的內容

例:

[root@lxc ~]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-")'

2008-08-08 08-08-08

[root@lxc ~]#

? split(s,array,[r]) :以r 為分隔符,切割字符s,并將切割后的結果保存至array所表示的數組中,第一個索引值為1, 第二個索引值為2,…

例:

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

 7

172.16.253.83 1

0.0.0.0 6

[root@lxc ~]#

自定義函數

  格式:

function name ( parameter, parameter, … ) {

statements

return expression

}

例:

 

[root@lxc ~]# cat fun.awk

function funmin(num1,num2){

num1<num2?min=num1:min=num2

return min

}

BEGIN{n1=100; n2=200;print funmin(n1,n2)}

[root@lxc ~]# awk -f fun.awk

100

[root@lxc ~]#

  system 命令

  空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除awk的變量外其他一律用""引用起來。

例:

[root@lxc ~]# awk 'BEGIN{score=100;system("echo your score is " score)}'

your score is 100

[root@lxc ~]#

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

例:

[root@lxc ~]# cat f1.awk

#!/bin/awk -f

{if($3>=1000)print $1,$3}

[root@lxc ~]# ./f1.awk -F: /etc/passwd

nfsnobody 65534

[root@lxc ~]#

    向腳本傳遞參數

    格式:awkfile var=value var2=value2… Inputfile

例:

[root@lxc ~]# cat test.awk

#!/bin/awk -f

{if ($3>=min && $3<=max)print $1,$3}

 

[root@lxc ~]# ./test.awk -F: min=100 max=200 /etc/passwd

usbmuxd 113

avahi-autoipd 170

abrt 173

[root@lxc ~]#

原創文章,作者:changge,如若轉載,請注明出處:http://www.www58058.com/61516

(0)
changgechangge
上一篇 2016-11-29
下一篇 2016-11-29

相關推薦

  • 用戶和組的簡介

     在第二周的學習中,關于用戶和組是一個難點,也是重點,本篇博客則是對用戶和組的簡單闡述,如有錯誤或不足還請各位大牛指出,在此謝過! 1、用戶 # 1.1用戶的定義      通過前面對Linux 多用戶的理解,我們明白Linux 是真正意義上的多用戶操作系統,所以我們能在Linux系統中建若干用戶(…

    Linux干貨 2017-07-22
  • Linux程序包管理方式

    Linux程序包安裝和管理方式共計三種:          一、[yum|dnf],通過官網或者其他開源網站提供的文件服務器,本機鏡像源等途徑進行安裝。         二、rpm,通過官網或者其他開源網站通過…

    Linux干貨 2016-08-29
  • 設計模式(四)原型模式Prototype(創建型)

    1.   概述 我們都知道,創建型模式一般是用來創建一個新的對象,然后我們使用這個對象完成一些對象的操作,我們通過原型模式可以快速的創建一個對象而不需要提供專門的new()操作就可以快速完成對象的創建,這無疑是一種非常有效的方式,快速的創建一個新的對象。 例子1:孫悟空拔下一嘬猴毛,輕輕一吹就會變出好多的孫悟空來。 例子2:寄個快遞下面是一個郵寄快…

    Linux干貨 2015-06-25
  • 基于Python和MoviePy庫實現數據的動態展示

    基于Python和MoviePy庫實現數據的動態展示 (翻譯:以馬內利)  原文鏈接:Data Animations With Python and MoviePy   Python擁有很多實現數據可視化的庫,但是很少可以展示GIFs的動態視圖。 這篇博客主要介紹怎樣使用MoviePy庫作為一個其他可視化庫的通用插件。 Movi…

    2015-03-26
  • 二、(1)Linux常用文件管理類命令詳解

    Linux 文件管理 命令 cp mv rm

    2018-01-08
  • 馬哥Linux第三周作業

    正則表達式 用戶和組管理

    Linux干貨 2017-12-31
欧美性久久久久