三劍客——AWK

weixin_17-CD發表於2020-10-09

功能:彙總、處理資料,對資料進行整理
概述:
awk的名稱來自於最初設計者
Alfred V. Aho
J. Weinberger
Brian W. Kernighan
awk最原始的版本是1977年在AT&T貝爾實驗室誕生的,awk經過改進生成的新的版本nawk,gawk,現在預設linux系統下日常使用的是gawk.

工作流程:
逐行掃描檔案,從第一行開始,到最後一行
匹配符合條件的行,在這些行上做指定的操作

基本結構:
模式{動作}

兩種特殊模式
BEGIN
放在讀取資料之前執行
一般用來列印表頭,初始化分隔符,定義變數
END
所有資料讀取完之後執行
彙總

在讀取檔案內容前,執行BEGIN後面的指令
然後讀檔案內容並判斷是否滿足特定的模式,如果滿足,執行模式後面的指令
最後執行END模式指定

基本語法:
awk [選項] ‘/模式匹配/{處理動作1,處理動作2…}’ 檔名

awk的變數
內建變數
$0 表示一整行內容
$1-$100
$1 表示第一個欄位
$2 表示第二個欄位
例子:awk的簡單操作
[root@ops14 20200803]# cat test
Renxiang is a good boy.
Today is Monday.
[root@ops14 20200803]# awk ‘{print $1}’ test
Renxiang
Today
[root@ops14 20200803]# awk ‘{print $2}’ test
is
is
[root@ops14 20200803]# awk ‘{print $3}’ test
a
Monday.

與記錄相關的變數(記錄就是行)
FS:讀取檔案的分隔符(輸入分隔符,預設是空格)
OFS:輸出欄位的分隔符(輸出分隔符,預設是空格)
RS:記錄的分隔符(行分隔符,預設是換行符)
ORS:輸出記錄分隔符

例子:
輸出/etc/passwd檔案中的使用者名稱和家目錄,中間用@分割
awk ‘BEGIN{FS=":";OFS="@"}{print $1,$6}’ /etc/passwd

練習:
輸出/etc/passwd檔案中的使用者名稱和預設shell,用~分割

例子:RS(行分隔符,預設是換行符)
[root@ops14 20200803]# cat test
Renxiang is a good boy.
Today is Monday.
[root@ops14 20200803]# awk ‘BEGIN{RS=" "}{print $0}’ test
Renxiang
is
a
good
boy.
Today
is
Monday.
[root@ops14 20200803]# awk ‘BEGIN{ORS=";"}{print $0}’ test
Renxiang is a good boy.;Today is Monday.;[root@ops14 20200803]#

練習:
test2內容如下:
name:aaa,email:xxx@xxx.com,name:bbb,email:abcd@abc.com,
要求用awk進行處理,讀檔案時把逗號當成換行符

與資料相關的變數
NR 行號,每處理完一行,NR+1
FNR 行號,處理多個檔案時,把兩個檔案的行號分開計算
NF 當前行的欄位數
$NF 當前行的最後一個欄位
$(NF-1) 當前行的倒數第二個欄位

檢視IP地址
ifconfig | head -2 | tail -1 | tr -s " " | cut -d " " -f 3
ifconfig | awk ‘NR==2{print $2}’

FILENAME 顯示檔名
[root@ops14 20200803]# cat haha
aa
bb
ccc
dd
[root@ops14 20200803]# cat heihei
111
2222
33
44
555
6666
[root@ops14 20200803]# awk ‘{print FILENAME,NR,$0}’ haha heihei
haha 1 aa
haha 2 bb
haha 3 ccc
haha 4 dd
heihei 5 111
heihei 6 2222
heihei 7 33
heihei 8 44
heihei 9 555
heihei 10 6666
[root@ops14 20200803]# awk ‘{print FILENAME,FNR,$0}’ haha heihei
haha 1 aa
haha 2 bb
haha 3 ccc
haha 4 dd
heihei 1 111
heihei 2 2222
heihei 3 33
heihei 4 44
heihei 5 555
heihei 6 6666
自定義變數
兩種定義方式
第一種 -v 變數名=變數值
第二種 在模式中直接定義

注意:給字串賦值,一定要有雙引號
變數名:數字、字母、下劃線組成,不能以數字開頭,不能是關鍵字

第一種
awk -v xx=“wo shi renxiang” ‘BEGIN{print xx}’

第二種
awk ‘BEGIN{xx=“renxiang”;print xx}’

[root@ops14 20200803]# cat student

  1. du 70 80 90
  2. ren 80 80 80
  3. xiang 90 90 90
    [root@ops14 20200803]# cat student.awk
    BEGIN{print"學號\t姓名\t語文\t數學\t英語\t總分\t"}
    {printf"%-s\t%-s\t%-d\t%-d\t%-d\t%-d\n",$1,$2,$3,$4,$5,sum=$3+$4+$5}

printf 格式化輸出,預設不換行
語法:
printf 格式 變數
格式都是%開頭,後面跟一個字元
%s 字串
%d 十進位制整數
%f 浮點數
%x 十六進位制
%o 八進位制
-左對齊,預設是右對齊

%4.2f 4代表寬度,2代表2位小數

例子:
格式化輸出使用者名稱和UID
awk ‘BEGIN{FS=":"}{printf"%-20s%d\n",$1,$3}’ /etc/passwd

格式化輸出使用者名稱和家目錄
awk ‘BEGIN{FS=":"}{printf"%-20s%s\n",$1,$6}’ /etc/passwd

printf總結:
1、使用printf需要指定格式
2、格式是用來指定後面每個變數的輸出方式
3、printf不會自動換行,需要手動新增\n
4、printf預設不輸出字元的分隔符

比較表示式
用來比較數字或字串

=
<
<=
==
!=

例子:
1、列印/etc/passwd中UID為0的行
awk ‘BEGIN{FS=":"}$3==0’ /etc/passwd

2、找出預設shell是/bin/bash的使用者
awk ‘BEGIN{FS=":"}$7=="/bin/bash"’ /etc/passwd

3、列印/etc/passwd檔案中GID為1000的行
awk ‘BEGIN{FS=":"}$4==1000’ /etc/passwd

4、找出系統中的普通使用者(UID>=1000)
awk ‘BEGIN{FS=":"}$3>=1000’ /etc/passwd

條件表示式
語法:
awk [選項] ‘{if(條件表示式){操作1}else{操作2}}’

例子:當UID0時,列印“管理員使用者,否則,列印“普通使用者”
awk -F : '{if($3
0){print $1"是管理員"}else{print $1"是普通用 戶"}’ pass10

awk ‘BEGIN{FS=":"}{if($3==0){print $1"是管理員"}else{print $1 “是普通使用者”}}’ pass10

算術運算

      • / %
        例子:
        列印100以內能被7整數的數字
        seq 100 | awk ‘$1%7==0{print}’

邏輯運算
&&
||
!
1、/etc/passwd中UID大於100且小於1000的使用者
awk -F : ‘$3>100 && $3<1000 {print $1,$3}’ /etc/passwd

3、UID大於100或預設shell是/sbin/nologin的使用者
awk -F “:” ‘$3>100 || $7=="/sbin/nologin"’ /etc/passwd

模式匹配
x~/y/ 匹配正則,y是正規表示式
例子:在/etc/passwd中查詢使用者名稱包含o的行
awk -F : ‘$1~/o/{print $0}’ /etc/passwd

查詢預設shell是bash結尾的行
awk -F : ‘ 7   / b a s h 7~/bash 7 /bash/{print $0}’ /etc/passwd

x!~/y/ 不匹配正則
在/etc/passwd中查詢使用者名稱包含o的行
awk -F : ‘$1!~/o/’ /etc/passwd

1-100中不包含7的數字
seq 100 | awk ‘$1!~/7/’

常見的模式
空模式
匹配所有的行
例子:列印所有使用者的使用者名稱
awk -F : ‘{print $1}’ pass10

固定模式
查詢預設shell是/bin/bash的行
awk -F : ‘$7~//bin/bash/’ /etc/passwd

範圍模式
(sed支援用行號或者正則指定地址)
awk不支援行號定界
查詢以bin開頭的行到adm開頭的行
awk -F : ‘/bin/,/adm/’ /etc/passwd

特殊模式
BEGIN
在沒有讀取任何資料之前執行
一般用於列印表頭、 初始化分隔符、定義變數
END
在所有資料讀取完之後執行
彙總資料

相關文章