GNU 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: 自定義變量

 

awk不能修改文件,只做輸出顯示處理

 

[root@localhost ~]# which awk

/usr/bin/awk

[root@localhost ~]# ll /usr/bin/awk

lrwxrwxrwx. 1 root root 4 Dec 14 21:53 /usr/bin/awk -> gawk

 

awk語言

  • 基本格式:awk [options] ‘program’ file…
  • program:pattern{action statements;..}
  • pattern和action:

pattern部分決定動作語句何時觸發及觸發事件

BEGIN,END

pattern決定了是針對那種類型的行進行處理。雖然默認把每一行都讀進來,但是讀進來的行要不要處理,可以定義pattern進行過濾,例如:如果滿足pattern就執行動作,不滿足就不符合條件,就可以直接跳到下一行開始。

action statements對數據進行處理,放在{}內指明。打印顯示必要的內容

print, printf

 

print:簡單的把必要的內容數據顯示出來

printf:更加具體詳細的定義顯示的格式,例如添加控制符,打印的時候字段和字段之間有多寬、小數點有多少位

 

  • 分割符、域和記錄

awk執行時,由分隔符分隔的字段(域)標記,分割成若干個列,每個列系統會自動分配變量$1,$2..$n對應的表示他們,用$1,$2..$n分別表示這一行的第幾列,稱為域標識。$0為所有域,注意:和shell中變量$符含義不同

文件的每一行稱為記錄默認回車換行分割記錄

省略action,則默認執行 print $0 的操作,打印一整行

$0為所有域,整行的所有字段

 

在bash中$0 表示程序本身

 

 

printf也是一個內部命令,作用和echo相似,按照一定格式顯示字符串

[root@localhost ~]# type printf

printf is a shell builtin

[root@localhost ~]# man printf

NAME

printf – format and print data 格式化和打印數據

 

記錄不一定非得是一行才成為一條記錄,例如:別的形式

[root@localhost ~]# vim file

a:bb;ccc:ddd;

例如該文件中,可以認為“:”分開的為字段,“;”分開的為記錄(一行),不是按照回車換行為記錄的分隔符,默認記錄的分割符是回車換行,也可以是別的字符

 

 

 

awk工作原理

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

 

  • 第二步:從文件或標準輸入(stdin)讀取一行,然后執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最后一行重復這個過程,直到文件全部被讀取完畢。

從命令的執行結果來的數據去讀取第一行,然后去執行pattern中的action,看是否符合pattern定義,如果符合pattern定義就執行里面的action,不符合就不處理,讀取下一行,知道文件處理完

 

  • 第三步:當讀至輸入流末尾時,執行END{action;…}語句塊

 

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

 

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

 

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

 

awk

  • print格式: print item1, item2, … item1表示要打印的字符,可以是普通字符串,也可以是要打印的列
  • 要點:

(1) 逗號分隔符

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

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

  • 示例:

awk ‘{print “hello,awk”}’

awk –F: ?‘{print}’ ?/etc/passwd

awk –F: ??‘{print “wang”}’ ??/etc/passwd

awk –F: ‘{print $1}’ ??/etc/passwd awk –F: ‘{print $0}’ ?/etc/passwd

awk –F: ‘{print $1”\t”$3}’ ?/etc/passwd tail –3 ?/etc/fstab |awk ‘{print $2,$4}’

 

例子:

如果pattern忽略不寫,就會處理所有行

每讀一行顯示一行,讀進來一看,pattern未定義,符合條件,符合條件就打印

[root@localhost /app]# awk ‘{print “hello”}’ /etc/issue

hello

hello

 

從標準輸入讀取輸入進行打印

[root@localhost /app]# awk ‘{print “hello”}’

a

hello

b

hello

 

awk可以讀取標準輸入

[root@localhost /app]# cat /etc/issue | awk ‘{print “hello”}’

hello

hello

hello

管道把前一個命令的標準輸出作為后一個命令的標準輸入

 

[root@localhost /app]# awk ‘{print “hello\nclass27″}’ /etc/centos-release

hello

class27

 

做數字運算,只要是字符串,就需要加引號引起來,數字不需要加引號

[root@localhost /app]# awk ‘{print 2*3}’ /etc/centos-release

6

[root@localhost /app]# awk ‘{print 2^3}’ /etc/centos-release

8

[root@localhost /app]# awk ‘{print 2/3}’ /etc/centos-release

0.666667

 

希望取出特定的字段,awk默認的分隔符是空格

[root@localhost /app]# awk -F “:” ‘{print $1,$3,$7}’ passwd

 

取分區的利用率

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $5}’

8%

1%

4%

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1,$5}’

/dev/sda2 8%

/dev/sda3 1%

/dev/sda1 4%

 

{print $1,$5},$1 和 $5 之間使用“,”,輸出時字段的分割符為空格,也可以進行指定,例如:

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1″——“$5}’

/dev/sda2——8%

/dev/sda3——1%

/dev/sda1——4%

 

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1”\t“$5}’

/dev/sda2 8%

/dev/sda3 1%

/dev/sda1 4%

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1”\n“$5}’

/dev/sda2

8%

/dev/sda3

1%

/dev/sda1

4%

$0打印整行內容

默認不寫也是打印整行內容

[root@localhost ~]# df | grep ‘dev/sd’ | awk ‘{ print }’

/dev/sda2 ??????52403200 16332416 ?36070784 ?32% /

/dev/sda5 ??????20961280 ???51048 ?20910232 ??1% /app

/dev/sda1 ???????1038336 ??227464 ???810872 ?22% /boot

 

[root@localhost ~]# df | grep ‘dev/sd’ | awk ‘{ print $0 }’

/dev/sda2 ??????52403200 16332416 ?36070784 ?32% /

/dev/sda5 ??????20961280 ???51048 ?20910232 ??1% /app

/dev/sda1 ???????1038336 ??227464 ???810872 ?22% /boot

 

 

 

awk變量

  • 變量:內置和自定義變量
  • FS:輸入字段分隔符,默認為空白字符

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

awk ?–F: ??‘{print $1,$3,$7}’ /etc/passwd

 

awk -v?FS=’:’?等價于 awk -F ‘:’

 

FS:field,稱為域、字段、列column、屬性

行,稱為記錄,record

 

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

awk ?-v FS=‘:’ ?-v OFS=‘:’ ‘{print $1,$3,$7}’ /etc/passwd

 

  • RS:輸入記錄分隔符,指定輸入時的換行符

awk -v RS=’ ‘ ‘{print }’ /etc/passwd

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

awk -v RS=’ ‘ -v ORS=’###’‘{print }’ /etc/passwd

  • NF:字段數量

awk ?-F: ‘{print NF}’ /etc/fstab,引用內置變量不用$

awk ?-F: ?‘{print $(NF-1)}’ ?/etc/passwd

  • NR:記錄號

awk ‘{print NR}’ ?/etc/fstab ; awk END'{print NR}’ ?/etc/fstab

 

-v表示給變量賦值,FS是awk自帶的變量,字段的分隔符,指定文件輸入的分隔符是什么

[root@localhost /app]# awk -F ‘:’ ‘{print $1,$3}’ passwd

[root@localhost /app]# awk -v FS=’:’?‘{print $1,$3}’ passwd

 

變量的好處是可以在awk中輸出時使用

[root@localhost /app]# awk -v FS=’:’ ‘{print $1,FS,$3}’ passwd

root : 0

bin : 1

 

awk還可以使用bash變量,例如調用bash中的變量

[root@localhost /app]# sep=”:”;awk -v FS=”$sep” ‘{print $1,FS,$3}’ passwd

root : 0

bin : 1

-F只能在外面使用bash中的變量,但是里面就無法使用了

[root@localhost ~]# sep=”:”;awk -F “$sep” ‘{print $1,”:”$3}’ passwd

root :0

bin :1

 

 

 

輸出分隔符

[root@localhost /app]# awk -v FS=’:’?-v OFS=’+’?‘{print $1,$3}’ passwd

root+0

bin+1

輸入分割符決定字段之間怎么分割進行處理

輸出分隔符決定字段之間怎么輸出進行顯示

 

把一個文件讀進來怎么知道怎樣算是一條記錄?默認回車換行是一條記錄

例如:認為一條記錄的分割符為‘;’,字段的分隔符默認為空白符

[root@localhost /app]# cat file

aa bb?cc;ee

ff?oo;xx

yy?zz

 

[root@localhost /app]# awk -v RS=”;”?‘{print $2}’ file

bb

ff

yy

 

[root@localhost /app]# cat file

a

b

c?aa

bb

cc?aaa

bb

ccc?aaa

以空格作為行的分隔符

[root@localhost /app]# awk -v RS=” ” ‘{ print $1,$2}’ file

a b

aa bb

aaa bb

aaa

以空格作為行的分隔符,所以abc算是一條記錄,默認字段的分割符為空白符,回車換行也是空白符,所以a是$1,b是$2,c是$3,所以第一行為a b

所以,記錄分別是:

a b c

aa bb cc

aaa bb ccc

aaa

輸出的時候一條一條的記錄默認是換行分割出來的,輸出的時候,記錄和記錄之間到的默認分割符是回車換行

指定輸出的分隔符

[root@localhost ~]# cat f2.txt

a b

aa bb

aaa bb

aaa

指定輸出記錄的分隔符

[root@localhost ~]# awk -v RS=” ” -v ORS=”—“?‘{print $1,$2}’ f2.txt

a —b aa—bb aaa—bb aaa—

 

字段數量NF

顯示每個行有多少個字段

[root@localhost ~]# awk -F: ‘{print NF}’ /etc/passwd

7

 

輸出最后一個字段

[root@localhost ~]# awk -F: ‘{print $NF}’ /etc/passwd

/bin/bash

 

輸出倒數第二個字段

[root@localhost ~]# awk -F: ‘{print $(NF-1)}’ /etc/passwd

/root

 

取出遠程連接IP

[root@localhost ~]# ss -nt | awk ‘{print $NF}’ | awk -F: ‘{print $1}’

Address

172.18.101.66

 

取出分區利用率

[root@localhost ~]# df | grep ‘/dev/sd’ | awk ‘{print $(NF-1)}’|awk -F% ‘{print $1}’

32

1

22

取http訪問日志

[root@localhost /app]# awk ‘{print $1}’ /var/log/httpd/access_log

172.18.101.66

 

NR:記錄號,每條記錄的編號

[root@localhost /app]# awk ‘{print NR,$0}’ /etc/passwd

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

 

空行也算行號

[root@localhost /app]# awk ‘{print NR,$0}’ /etc/fstab

1

2 #

3 # /etc/fstab

 

同時處理多個文件

[root@localhost /app]# awk ‘{print NR,$0}’ /etc/fstab /etc/issue

在第一個文件輸出完之后接著輸出第二個文件的內容

 

同時處理多個文件,每個文件獨立編號

[root@localhost /app]# awk ‘{print FNR,$0}’ /etc/fstab /etc/issue

1

2 #

3 # /etc/fstab

1 \S

2 Kernel \r on an \m

3

 

顯示文件名

[root@localhost /app]# awk ‘{print FNR,FILENAME,$0}’ /etc/fstab /etc/issue

1 /etc/fstab

2 /etc/fstab #

3 /etc/fstab # /etc/fstab

1 /etc/issue \S

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

3 /etc/issue

 

awk

  • FNR:各文件分別計數,記錄號

awk ‘{print FNR}’ ?/etc/fstab /etc/inittab

  • FILENAME:當前文件名

awk ‘{print FILENAME}’ ?/etc/fstab

  • ARGC:命令行參數的個數

awk ‘{print ARGC}’ ?/etc/fstab /etc/inittab

awk ‘BEGIN {print ARGC}’ ?/etc/fstab /etc/inittab

 

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

awk ‘BEGIN {print ARGV[0]}’ ?/etc/fstab /etc/inittab

awk ‘BEGIN {print ARGV[1]}’ ?/etc/fstab /etc/inittab

 

命令行參數的個數

[root@localhost ~]# awk ‘{print ARGC}’ /etc/fstab /etc/issue

3

[root@localhost /app]# awk ‘{print ARGV[0]}’ /etc/fstab /etc/issue

awk

[root@localhost /app]# awk ‘{print ARGV[1]}’ /etc/fstab /etc/issue

/etc/fstab

[root@localhost /app]# awk ‘{print ARGV[2]}’ /etc/fstab /etc/issue

/etc/issue

三個參數從0開始編,認為awk也是參數之一

 

 

awk變量

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

(1) -v var=value

(2) 在program中直接定義

  • 示例:

awk -v test=’hello gawk’ ‘{print test}’ /etc/fstab

awk -v test=’hello gawk’ ‘BEGIN{print test}’

awk ‘BEGIN{test=”hello,gawk”;print test}’

awk –F:‘{sex=“male”;print $1,sex,age;age=18}’ /etc/passwd

cat awkscript ?{print script,$1,$2} ?awk -F: -f awkscript script=“awk” /etc/passwd

 

自定義變量

#?awk -v sep=”:”?-F: ‘{print $1sep$3}’ /etc/passwd

root:0

 

分別進行定義

# awk -v uid=”uid” -F: ‘{user=”username”;print user”:”$1,uid”:”$3}’ /etc/passwd

username:root uid:0

 

#?awk -v user=”username”?-v uid=”uid”?-F: ‘{print user”:”$1,uid”:”$3}’ /etc/passwd

username:root uid:0

 

在program中直接定義

# awk -F: ‘{user=”username”;uid=”uid”; print user”:”$1,uid”:”$3}’ /etc/passwd

username:root uid:0

定義在awk程序里面不能使用bash中的變量,在外部定義可以使用bash中的變量

 

# u=”user”;?awk -F: -v user=”$u”?‘{uid=”uid”; print user”:”$1,uid”:”$3}’ /etc/passwd

user:root uid:0

 

 

先使用后定義會現第一行不生效的問題

# awk -F: ‘{print user”:”$1,uid”:”$3;user=”user”;uid=”userid”}’ /etc/passwd

:root :0

user:bin userid:1

原因:第一行讀取進來進行處理的時候,user和uid還是未定義的狀態,但是到第二行的時候,就已經是定義了的狀態了。這一行定義的變量將會在下一行起作用。為避免出現問題,建議先聲明后使用

 

 

把awk的指定放入文件中

[root@localhost ~]# cat awk.script

{user=”username”;uid=”userid”;print user”:”$1,uid”:”$3}

 

[root@localhost ~]# awk -F: -f awk.script?/etc/passwd

username:root userid:0

本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/90685

(0)
無言勝千言無言勝千言
上一篇 2017-12-31 19:35
下一篇 2018-01-01 15:38

相關推薦

  • 【知識點】NO.1—-關于刪除文件后未及時釋放磁盤空間問題

    刪除了某些占用大存儲的文件,發現占用的磁盤空間并沒有的到釋放。怎么解決呢?
    在工作中經常遇到服務器某個存放日志或者某些數據的磁盤(或者目錄),因為檢查不及時磁盤存儲滿了的狀況。釋放空間真的只是刪除文件這么簡單嗎?nonono…

    2017-11-18
  • 學習目標

    先把落下的課補上……

    Linux干貨 2016-10-31
  • 第六周作業

    請詳細總結vim編輯器的使用并完成以下練習題 基本模式:     編輯模式,命令模式     輸入模式     末行模式         內置的命令行接口 打開…

    Linux干貨 2017-02-14
  • Linux基礎知識之GUN awk

    awk:報告生成器,格式化文本輸出    基本用法:    gawk [options] 'program' FILE …    options:     &…

    Linux干貨 2016-09-20
  • 馬哥教育網絡班22期+第4周課程練習

    1、復制/etc/skel目錄為/home/tuser1,要求/home/tuser1及其內部文件的屬組和其它用戶均沒有任何訪問權限。   cp -r /etc/skel /home/tuser1    chmod -R go=— /home/tuser1 2、編輯/etc/group文件,添加組hadoo…

    Linux干貨 2016-09-19
  • 文本編輯工具vim

                             vim +#: 打開文件直接處在#行 +/PATTERN:打開文件直接處在第一次匹配到行 vim + file :打開文件直接處在最后行 vim –b file :以二進制打開文件…

    Linux干貨 2016-08-12
欧美性久久久久