Linux實戰教學筆記18:linux三劍客之awk精講

Linux三劍客之awk精講(基礎與進階)

標籤(空格分隔): Linux實戰教學筆記-陳思齊html


快捷跳轉目錄:

* 第1章:awk基礎入門
* 1.1:awk簡介 * 1.2:學完awk你能夠掌握: * 1.3:awk環境簡介 * 1.4:awk的格式
* 1.5:模式動做 * 1.6:awk的執行過程 * 1.6.1:小結awk執行過程 * 1.7:記錄和字段
* 1.7.1:記錄(行) * 1.7.2:記錄分隔符-RS * 1.7.3:對$0的認識 * 1.7.4:企業面試題
* 1.7.5:awk記錄知識小結 * 1.7.6:字段(列) * 1.7.7:ORS與OFS簡介 * 1.9:awk基礎入門總結
* 第2章:awk進階
* 2.1:awk模式與動做 * 2.2:正則表達式做爲模式 * 2.2.1:awk正則匹配操做符 * 2.2.2:awk正則表達式匹配整行
* 2.2.3:awk正則表達式匹配一行中的某一列 * 2.2.4:某個區域中的開頭和結尾 * 2.2.5:建立測試環境 * 2.2.6:測試文件說明
* 2.2.7:awk正則表達式練習題 * 2.2.8:awk正則表達式練習題-詳解 * 2.2.9:企業面試題 * 2.2.10:明明白白擴展正則表達式:+(加號)
* 2.2.11:awk正則之{} -花括號 * 2.2.12:企業案例1 * 2.2.13:企業案例2 * 2.3:比較表達式作爲模式-須要一些例子
* 2.3.1:企業面試題 * 2.3.2:若是判斷某一列是否等於某個字符呢? * 2.4:範圍模式 * 2.5:awk特殊模式-BEGIN模式與END模式
* 2.5.1:BEGIN模塊 * 2.5.2:awk中變量的概念簡介 * 2.5.3:END模塊 * 2.6:awk中的動做
* 2.7:awk模式與動做小結 * 2.8:總結awk執行過程
* 2.9:awk數組 * 2.10:圖片-數組

第1章 awk基礎入門

要弄懂awk程序,必須熟悉瞭解這個工具的規則。本實戰筆記的目的是經過實際案例或面試題帶同窗們熟練掌握awk在企業中的用法,而不是awk程序的幫助手冊。mysql

1.1 awk簡介

  • 一種名字怪異的語言
  • 模式掃描和處理

awk不只僅時linux系統中的一個命令,並且是一種編程語言,能夠用來處理數據和生成報告(excel)。處理的數據能夠是一個或多個文件,能夠是來自標準輸入,也能夠經過管道獲取標準輸入,awk能夠在命令行上直接編輯命令進行操做,也能夠編寫成awk程序來進行更爲複雜的運用。本章主要講解awk命令的運用。linux

1.2 學完awk你能夠掌握:

  1. 記錄與字段
  2. 模式匹配:模式與動做
  3. 基本的awk執行過程
  4. awk經常使用內置變量(預約義變量)
  5. awk數組(工做經常使用)
  6. awk語法:循環,條件
  7. awk經常使用函數
  8. 向awk傳遞參數
  9. awk引用shell變量
  10. awk小程序及調試思路

1.3 awk環境簡介

[root@chensiqi1 ~]# cat /etc/redhat-release 
CentOS release 6.8 (Final)
[root@chensiqi1 ~]# uname -r
2.6.32-642.el6.x86_64
[root@chensiqi1 ~]# ll `which awk`
lrwxrwxrwx. 1 root root 4 Dec 23 20:25 /bin/awk -> gawk
[root@chensiqi1 ~]# awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.

1.4 awk的格式

  • awk指令是由模式,動做,或者模式和動做的組合組成。
  • 模式既pattern,能夠相似理解成sed的模式匹配,能夠由表達式組成,也能夠是兩個正斜槓之間的正則表達式。好比NR==1,這就是模式,能夠把他理解爲一個條件。
  • 動做即action,是由在大括號裏面的一條或多條語句組成,語句之間使用分號隔開。好比awk使用格式:

屏幕快照 2017-02-25 下午11.18.03.png-277.4kB

awk處理的內容能夠來自標準輸入(<),一個或多個文本文件或管道。面試

屏幕快照 2017-02-25 下午11.31.52.png-327.9kB

  • pattern既模式,也能夠理解爲條件,也叫找誰,你找誰?高矮,胖瘦,男女?都是條件,既模式。
  • action既動做,能夠理解爲幹啥,找到人以後你要作什麼。
    模式和動做的詳細介紹咱們放在後面部分,如今你們先對awk結構有一個瞭解。

1.5 模式動做

示例1-1: 基本的模式和動做正則表達式

[root@chensiqi1 ~]# awk -F ":" 'NR>=2 && NR<=6{print NR,$1}' /etc/passwd
2 bin
3 daemon
4 adm
5 lp
6 sync
命令說明:
-F 指定分隔符爲冒號,至關於以「:」爲菜刀,進行字段的切割。
NR>=2 && NR<=6:這部分表示模式,是一個條件,表示取第2行到第6行。
{print NR,$1}:這部分表示動做,表示要輸出NR行號和$1第一列。

示例1-2 只有模式redis

[root@chensiqi1 ~]# awk -F ":" 'NR>=2&&NR<=6' /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
sync:x:5:0:sync:/sbin:/bin/sync

命令說明:
-F指定分隔符爲冒號
NR>=2&&NR<=6這部分是條件,表示取第2行到第6行。
可是這裏沒有動做,這裏你們須要瞭解若是隻有條件(模式)沒有動做,awk默認輸出整行

示例1-3:只有動做算法

[root@chensiqi1 ~]# awk -F ":" '{print NR,$1}' /etc/passwd
1 root
2 bin
3 daemon
4 adm
5 lp
6 sync
7 shutdown
8 halt
9 mail
10 uucp
如下省略....

命令說明:
-F指定分隔符爲冒號
這裏沒有條件,表示對每一行都處理
{print NR,$1}表示動做,顯示NR行號與$1第一列
這裏要理解沒有條件的時候,awk會處理每一行。

示例1-4:多個模式和動做sql

[root@chensiqi1 ~]# awk -F ":" 'NR==1{print NR,$1}NR==2{print NR,$NF}' /etc/passwd
1 root
2 /sbin/nologin

命令說明:
-F指定分隔符爲冒號
這裏有多個條件與動做的組合
NR==1表示條件,行號(NR)等於1的條件知足的時候,執行{print NR,$1}動做,輸出行號與第一列。
NR==2表示條件,行號(NR)等於2的條件知足的時候,執行{print NR,$NF}動做,輸出行號與最後一列($NF)

注意:shell

  • Pattern和{Action}須要用單引號引發來,防止shell做解釋。
  • Pattern是可選的。若是不指定,awk將處理輸入文件中的全部記錄。若是指定一個模式,awk則只處理匹配指定的模式的記錄。
  • {Action}爲awk命令,能夠是但個命令,也能夠多個命令。整個Action(包括裏面的全部命令)都必須放在{ 和 }之間。
  • Action必須被{ }包裹,沒有被{ }包裹的就是Patern
  • file要處理的目標文件

1.6 awk執行過程

在深刻了解awk前,咱們須要知道awk如何處理文件的。編程

示例1-5 示例文件的建立

[root@chensiqi1 ~]# mkdir /server/files/ -p
[root@chensiqi1 ~]# head /etc/passwd > /server/files/awkfile.txt
[root@chensiqi1 ~]# cat /server/files/awkfile.txt 
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

這個文件僅包含十行文件,咱們使用下面的命令:

示例1-6 awk執行過程演示

[root@chensiqi1 ~]# awk 'NR>=2{print $0}' /server/files/awkfile.txt 
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

命令說明:
條件NR>=2,表示行號大於等於2時候,執行{print $0}顯示整行。
awk是經過一行一行的處理文件,這條命令中包含模式部分(條件)和動做部分(動做),awk將處理模式(條件)指定的行

1.6.1 小結awk執行過程

1)awk讀入第一行內容

2)判斷是否符合模式中的條件NR>=2

a,若是匹配則執行對應的動做{print $0}
b,若是不匹配條件,繼續讀取下一行

3)繼續讀取下一行
4)重複過程1-3,直到讀取到最後一行(EOF:end of file)

屏幕快照 2017-02-26 上午10.46.53.png-271.3kB

1.7 記錄和字段

接下來我給你們帶來兩個新概念記錄和字段,這裏爲了方便你們理解能夠把記錄就看成行即記錄==行,字段至關於列,字段==列。

名稱 含義
record 記錄,行
field 域,區域,字段,列

1.7.1 記錄(行)

查看一下下面這段文字

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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

思考:
一共有多少行呢?你如何知道的?經過什麼標誌?

awk對每一個要處理的輸入數據認爲都是具備格式和結構的,而不只僅是一堆字符串。默認狀況下,每一行內容都是一條記錄,並以換行符分隔(\n)結束

1.7.2 記錄分隔符-RS

屏幕快照 2017-02-26 上午10.57.23.png-442.1kB

  • awk默認狀況下每一行都是一個記錄(record)
  • RS既record separator輸入輸出數據記錄分隔符,每一行是怎麼沒的,表示每一個記錄輸入的時候的分隔符,既行與行之間如何分隔。
  • NR既number of record 記錄(行)號,表示當前正在處理的記錄(行)的號碼。
  • ORS既output record separator 輸出記錄分隔符。

awk使用內置變量RS來存放輸入記錄分隔符,RS表示的是輸入的記錄分隔符,這個值能夠經過BEGIN模塊從新定義修改。

示例1-1:使用「/」爲默認記錄分隔符
示例文件:

[root@chensiqi1 ~]# cat /server/files/awkfile.txt 
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
[root@chensiqi1 ~]# awk 'BEGIN{RS="/"}{print NR,$0}' /server/files/awkfile.txt 
1 root:x:0:0:root:
2 root:
3 bin
4 bash
bin:x:1:1:bin:
5 bin:
6 sbin
7 nologin
daemon:x:2:2:daemon:
8 sbin:
9 sbin
10 nologin
adm:x:3:4:adm:
11 var
12 adm:
13 sbin
14 nologin
lp:x:4:7:lp:
15 var
16 spool
17 lpd:
18 sbin
19 nologin
sync:x:5:0:sync:
20 sbin:
21 bin
22 sync
shutdown:x:6:0:shutdown:
23 sbin:
24 sbin
25 shutdown
halt:x:7:0:halt:
26 sbin:
27 sbin
28 halt
mail:x:8:12:mail:
29 var
30 spool
31 mail:
32 sbin
33 nologin
uucp:x:10:14:uucp:
34 var
35 spool
36 uucp:
37 sbin
38 nologin

命令說明:
在每行的開始先打印輸出NR(記錄號行號),並打印出每一行$0(整行)的內容。
咱們設置RS(記錄分隔符)的值爲「/」,表示一行(記錄)以「/」結束
在awk眼中,文件是從頭至尾一段連續的字符串,恰巧中間有些\n(回車換行符),\n也是字符哦。

咱們回顧下「行(記錄)」究竟是什麼意思?

  • 行(記錄):默認以\n(回車換行)結束。而這個行的結束不就是記錄分隔符嘛。
  • 因此在awk中,RS(記錄分隔符)變量表示着行的結束符號(默認是回車換行)

在工做中,咱們能夠經過修改RS變量的值來決定行的結束標誌,最終來決定「每行」的內容。
爲了方便人們理解,awk默認就把RS的值設置爲「\n」

注意:
awk的BEGIN模塊,我會在後面(模式-BEGIN模塊)詳細講解,此處你們僅須要知道在BEGIN模塊裏面咱們來定義一些awk內置變量便可。

1.7.3 對$0的認識

  • 如1.7.2的例子,能夠看出awk中$0表示整行,其實awk使用$0來表示整條記錄。記錄分隔符存在RS變量中,或者說每一個記錄以RS內置變量結束。
  • 另外,awk對每一行的記錄號都有一個內置變量NR來保存,每處理完一條記錄,NR的值就會自動+1
  • 下面經過示例來加深印象。

示例1-2:NR記錄號

[root@chensiqi1 ~]# awk '{print NR,$0}' /server/files/awkfile.txt 
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

命令說明:
NR既number of record,當前記錄的記錄號,剛開始學也能夠理解爲行號。
$0表示整行或者說整個記錄

1.7.4 企業面試題:按單詞出現頻率降序排序(計算文件中每一個單詞的重複數量)

注:(此處使用sort與uniq便可)

題目:

題目建立方法:
sed -r '1,10s#[^a-zA-Z]+# #g' /etc/passwd>/server/files/count.txt

[root@chensiqi1 files]# cat /server/files/count.txt 
root x root root bin bash
bin x bin bin sbin nologin
daemon x daemon sbin sbin nologin
adm x adm var adm sbin nologin
lp x lp var spool lpd sbin nologin
sync x sync sbin bin sync
shutdown x shutdown sbin sbin shutdown
halt x halt sbin sbin halt
mail x mail var spool mail sbin nologin
uucp x uucp var spool uucp sbin nologin

思路:

讓全部單詞排成一列,這樣每一個單詞都是單獨的一行

1)設置RS值爲空格
2)將文件裏面的全部空格替換爲回車換行符「\n」
3)grep全部連續的字母,grep -o參數讓他們排成一列。

方法一:

[root@chensiqi1 files]# awk 'BEGIN{RS="[ ]+"}{print $0}' count.txt | sort |uniq -c|sort
      1 
      1 bash
      1 lpd
      2 daemon
      2 lp
      3 adm
      3 halt
      3 mail
      3 root
      3 shutdown
      3 spool
      3 sync
      3 uucp
      4 var
      5 bin
      6 nologin
     10 x
     12 sbin

方法二:

[root@chensiqi1 files]# cat count.txt | tr " " "\n" | sort | uniq -c | sort
      1 bash
      1 lpd
      2 daemon
      2 lp
      3 adm
      3 halt
      3 mail
      3 root
      3 shutdown
      3 spool
      3 sync
      3 uucp
      4 var
      5 bin
      6 nologin
     10 x
     12 sbin

方法三:

[root@chensiqi1 files]# grep -o "[a-zA-Z]\+" count.txt | sort | uniq -c | sort
      1 bash
      1 lpd
      2 daemon
      2 lp
      3 adm
      3 halt
      3 mail
      3 root
      3 shutdown
      3 spool
      3 sync
      3 uucp
      4 var
      5 bin
      6 nologin
     10 x
     12 sbin

1.7.5 awk記錄知識小結

  1. NR存放着每一個記錄的號(行號)讀取新行時候會自動+1
  2. RS是輸入數據的記錄的分隔符,簡單理解就是能夠指定每一個記錄的結尾標誌。
  3. RS做用就是表示一個記錄的結束
  4. 當咱們修改了RS的值,最好配合NR(行)來查看變化,也就是修改了RS的值經過NR查看結果,調試awk程序。
  5. ORS輸出數據的記錄的分隔符

awk學習技巧一則:
大象放冰箱分幾步?打開冰箱,把大象放進去,關閉冰箱門。
awk也是同樣的,一步一步來,先修改了RS,而後用NR調試,看看到底如何分隔的。而後經過sort排序,uniq -c去重

1.7.6 字段(列)

  • 每條記錄都是由多個區域(field)組成的,默認狀況下區域之間的分隔符是由空格(即空格或製表符)來分隔,而且將分隔符記錄在內置變量FS中,每行記錄的區域數保存在awk的內置變量NF中。

屏幕快照 2017-02-26 下午3.56.17.png-576.4kB

  • FS既field separator,輸入字段(列)分隔符。分隔符就是菜刀,把一行字符串切爲不少個區域。
  • NF既number of fileds,表示一行中列(字段)的個數,能夠理解爲菜刀切過一行後,切成了多少份。

OFS輸出字段(列)分隔符

  • awk使用內置變量FS來記錄區域分隔符的內容,FS能夠在命令行上經過-F參數來更改,也能夠經過BEGIN模塊來更改。
  • 而後經過$n,n是整數,來取被切割後的區域,$1取第一個區域,$2取第二個區域,$NF取最後一個區域。

下面咱們經過示例來增強學習。

示例1-3:指定分隔符

[root@chensiqi1 files]# awk -F ":" 'NR>=2&&NR<=5{print $1,$3}' /server/files/awkfile.txt 
bin 1
daemon 2
adm 3
lp 4

命令說明:
以:(冒號)爲分隔符,顯示第2行到第5行之間的第一區域和第三區域。
  • 此處的FS知識一個字符,其實它能夠指定多個的,此時FS指定的值能夠是一個正則表達式。
  • 正常狀況下,當你指定分隔符(非空格)的時候,例如指定多個區域分隔符,每一個分隔符就是一把刀,把左右兩邊切爲兩個部分。

企業面試題:同時取出chensiqi和215379068這兩個內容(指定多分隔符)

[root@chensiqi1 files]# echo "I am chensiqi,my qq is 1234567890">>/server/files/chensiqi.txt
[root@chensiqi1 files]# cat /server/files/chensiqi.txt 
I am chensiqi,my qq is 1234567890

同時取出chensiqi和1234567890這兩個內容。

思路:
咱們用默認的想法一次使用一把刀,須要配合管道的。如何同時使用兩把刀呢?看下面的結果

[root@chensiqi1 files]# awk -F "[ ,]" '{print $3,$NF}' /server/files/chensiqi.txt 
chensiqi 1234567890

命令說明:
經過命令-F參數指定區域分隔符
[ ,]是正則表達式裏面的內容,它表示一個總體,「一個」字符,既空格或者逗號(,),合併在一塊兒,-F 「[ ,]」就表示以空格或者逗號(,)爲區域分隔符

小技巧:
在動做(‘{print $3,$NF}’)裏面的逗號,表示空格,其實動做中的逗號就是OFS的值,咱們會在後面說明。剛開始你們把動做中的都逗號,看成空格便可。

示例:默認分隔符和指定分隔符會有些差別

[root@chensiqi1 files]# ifconfig eth0 | awk 'NR==2' >/server/files/awkblank.txt
[root@chensiqi1 files]# cat /server/files/awkblank.txt 
          inet addr:192.168.197.133  Bcast:192.168.197.255  Mask:255.255.255.0
#默認分隔符時候
[root@chensiqi1 files]# awk '{print $1}' /server/files/awkblank.txt 
inet
#指定分隔符時候
[root@chensiqi1 files]# awk -F "[ :]+" '{print $1}' /server/files/awkblank.txt 

[root@chensiqi1 files]# awk -F "[ :]+" '{print $2}' /server/files/awkblank.txt 
inet

命令說明:
awk默認的FS分隔符對於空格序列,一個空格或多個空格tab都認爲是同樣的,一個總體。
  • 這個文件的開頭有不少連續的空格,而後纔是inet這個字符
  • 當咱們使用默認的分隔符的時候,$1是有內容的。
  • 當咱們指定其餘分隔符(非空格)時候,區域會有所變化
  • 到底爲什麼會這樣,咱們在這裏再也不深刻研究,只要瞭解有這種狀況,注意一下便可。

1.7.7 ORS與OFS簡介

如今說說ORS和OFS這兩個內置變量的含義。

  • RS是輸入記錄分隔符,決定awk如何讀取或分隔每行(記錄)
  • ORS表示輸出記錄分隔符,決定awk如何輸出一行(記錄)的,默認是回車換行(\n)
  • FS是輸入區域分隔符,決定awk讀入一行後如何再分爲多個區域。
  • OFS表示輸出區域分隔符,決定awk輸出每一個區域的時候使用什麼分隔她們。
  • awk無比強大,你能夠經過RS,FS決定awk如何讀取數據。你也能夠經過修改ORS,OFS的值指定awk如何輸出數據。

屏幕快照 2017-02-26 下午5.29.13.png-544.9kB

1.8 字段與記錄小結

如今你應該會對awk的記錄字段有所瞭解了,下面咱們總結一下,學會給階段性知識總結是學好運維的必備技能。

屏幕快照 2017-02-26 下午6.22.15.png-649.4kB

  • RS記錄分隔符,表示每行的結束標誌
  • NR行號(記錄號)
  • FS字段分隔符,每列的分隔標誌或結束標誌
  • NF就是每行有多少列,每一個記錄中字段的數量
  • $符號表示取某個列(字段),$1$2$NF
  • NF表示記錄中的區域(列)數量,$NF取最後一個列(區域。)
  • FS(-F)字段(列)分隔符,-F(FS)「:」<==>‘BEGIN{FS=':'}’
  • RS 記錄分隔符(行的結束標識)
  • NR 行號
  • 選好合適的刀FS(***),RS,OFS,ORS
  • 分隔符==>結束標識
  • 記錄與區域,你就對咱們所謂的行與列,有了新的認識(RS,FS)

1.9 awk基礎入門總結

到了這裏咱們回頭看看,咱們以前學習的內容。

  • awk的命令行結構
  • awk的模式和動做
  • awk的記錄和字段

比較核心經常使用的是字段。
另外這些企業面試題但是學會awk的必備,必須本身也能寫出來。

第2章 awk進階

2.1 awk模式與動做

接下來就詳細介紹下,awk的模式都有幾種:

  • 正則表達式做爲模式
  • 比較表達式做爲模式
  • 範圍模式
  • 特殊模式BEGIN和END

awk的模式是你玩好awk的必備也是最基礎的內容,必須熟練掌握

2.2 正則表達式做爲模式

awk同sed同樣也能夠經過模式匹配來對輸入的文本進行匹配處理。說到模式匹配,確定少不了正則表達式,awk也支持大量的正則表達式模式,大部分與sed支持的元字符相似,並且正則表達式是玩轉三劍客的必備工具,下表列出了awk支持的正則表達式元字符:

awk默認就支持的元字符:

元字符 功能 示例 解釋
^ 字符串開頭 /^chensiqi/或$3~/^chensiqi/ 匹配全部以chensiqi開頭的字符串;匹配出全部第三列中以chensiqi開頭的
$ 字符串結尾 /chensiqi$/或$3~/chensiqi$/ 匹配全部以chensiqi結尾的字符串;匹配第三列中以chensiqi結尾的
.(點) 匹配任意但個字符(包括回車符) /c..l/ 匹配字母c,而後兩個任意字符,再以l結尾的行
* 重複0個或多個前一個字符 /a*cool/ 匹配0個或多個a以後緊跟着cool的行
+ 重複前一個字符一次或屢次 /a+b/ 匹配一個或多個a加上字符串b的行
? 匹配0個或一個前邊的字符 /a?b/ 匹配以字母a或b或c開頭的行
[] 匹配指定字符組內的任一個字符 /^[abc]/ 匹配以字母a或b或c開頭的行
[^] 匹配不在指定字符組內的任一字符 /^[^abc]/ 匹配不以字母a或b或c開頭的行
() 子表達式組合 /(chensiqi)+/ 表示一個或多個cool組合,當有一些字符須要組合時,使用括號括起來
| 或者的意思 /(chensiqi)|B/ 匹配chensiqi或字母B的行

awk默認不支持的元字符:(參數--posix)

元字符 功能 示例 解釋
x{m} x字符重複m次 /cool{5}/ 匹配l字符5次
x{m,} x字符重複至少m次 /(cool){2,}/ 匹配cool總體,至少2次
x{m,n} x字符重複至少m次,但不超過n次 /(cool){5,6}/ 匹配cool總體,至少5次,最多6次

提示:

  • 加括號表明總體匹配,不加那麼就匹配前邊的一個字符。awk默認不支持這種形式的正則,須要加--posix參數或者--re-interval
  • 正則表達式的運用,默認是在行內查找匹配的字符串,如有匹配則執行action操做,可是有時候僅須要固定的列來匹配指定的正則表達式,好比:我想取/etc/passwd文件中第五列{$5}這一列查找匹配mail字符串的行,這樣就須要用另外兩個匹配操做符,而且awk裏面只有這兩個操做符來匹配正則表達式。

2.2.1 awk正則匹配操做符

awk正則匹配操做符:
|~|用於對記錄或區域的表達式進行匹配|
|--|--|
|!~|用於表達與~相反的意思|

下面仍是經過具體示例來看看,awk如何來經過正則表達式匹配字符串的

2.2.2 awk正則表達式匹配整行

[root@chensiqi1 files]# awk -F ":" '/^root/' awkfile.txt 
root:x:0:0:root:/root:/bin/bash

和下面的效果是同樣的

[root@chensiqi1 files]# awk -F ":" '$0~/^root/' awkfile.txt 
root:x:0:0:root:/root:/bin/bash

提示:

awk只用正則表達式的時候是默認匹配整行的即‘$0~/^root/’和‘/^root/’是同樣的。

2.2.3 awk正則表達式匹配一行中的某一列

[root@chensiqi1 files]# awk -F ":" '$5~/shutdown/' awkfile.txt 
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

提示:

  • $5表示第五個區域(列)
  • ~表示匹配(正則表達式匹配)
  • /shutdown/表示匹配shutdown這個字符串

合併在一塊兒

$5~/shutdown/表示第五個區域(列)匹配正則表達式/shutdown/,既第5列包含shutdown這個字符串,則顯示這一行。

2.2.4 某個區域中的開頭和結尾

知道了如何使用正則表達式匹配操做符以後,咱們來看看awk正則與grep和sed不一樣的地方。

awk正則表達式
|^|匹配一個字符串的開頭|
|--|--|
|$|匹配一個字符串的結尾|

在sed和grep這兩個命令中,咱們都把它們看成行的開頭和結尾。可是在awk中他表示的是字符串的開頭和結尾。

接下來咱們經過練習題來聯繫awk如何使用正則表達式。

2.2.5 建立測試環境

[root@chensiqi1 ~]# cat >>/server/files/reg.txt<<KOF
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
KOF

2.2.6 測試文件說明

Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175

說明:

  • 第一列是姓氏
  • 第二列是名字
  • 第一列第二列合起來就是姓名
  • 第三列是對應的ID號碼
  • 最後三列是三次捐款數量

2.2.7 awk正則表達式練習題

練習題1:顯示姓Zhang的人的第二次捐款金額及她的名字

練習題2:顯示Xiaoyu的名字和ID號碼

練習題3:顯示全部以41開頭的ID號碼的人的全名和ID號碼

練習題4:顯示全部以一個D或X開頭的人名全名

練習題5:顯示全部ID號碼最後一位數字是1或5的人的全名

練習題6:顯示Xiaoyu的捐款,每一個值都有以$開頭。如$520$200$135

練習題7:顯示全部人的全名,以姓,名的格式顯示,如Meng,Feixue

2.2.8 awk正則表達式練習題-詳解

示例1:顯示姓Zhang的人的第二次捐款金額及她的名字

[root@chensiqi1 files]# cat reg.txt 
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ :]+" '$1~/^Zhang/{print $2,$(NF-1)}' reg.txt 
Zhang 100
Zhang 90

說明:

  • -F指定分隔符,如今你們知道了-F即FS也是支持正則表達式的。
  • 【 :】+ 表示連續的空格或冒號
  • -F 「【 :】+」 以連續的空格或冒號爲分隔符
  • /Zhang/表示條件,整行中包含Dan字符的這個條件。
  • {print $1,$(NF-1)} 表示動做,知足條件後,執行顯示第一列($1)和倒數第二列($(NF-1))固然$5也能夠。

注意:
NF是一行中有多少列,NF-1整行就是倒數第二列。
$(NF-1)就是取倒數第二列內容。

示例2:顯示Xiaoyu的姓氏和ID號碼

[root@chensiqi1 files]#cat reg.txt  
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ :]+" '$2~/^Xiaoyu/{print $1,$3}' reg.txt 
Zhang 390320151

命令說明:
指定分隔符-F 「【:】+」
$2~/Xiaoyu/表示條件,第二列包含Xiaoyu時候執行對應的動做
{print $1,$3}表示動做,顯示第一列和第三列的內容

示例3:顯示全部以41開頭的ID號碼的人的全名和ID號碼

[root@chensiqi1 files]# cat reg.txt 
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ :]+" '$3~/^(41)/{print $1,$2,$3}' reg.txt 
Zhang Dandan 41117397
Liu Bingbing 41117483

示例4:顯示全部以一個D或X開頭的人名全名

[root@chensiqi1 files]# cat reg.txt 
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ :]+" '$2~/^D|^X/{print $1,$2}' reg.txt 
Zhang Dandan
Zhang Xiaoyu
Wang Xiaoai

命令說明:
-F 「【 :】+」指定分隔符
|表示或,^以...開頭

注意:
這裏要用()括號表示即^(D|X)至關於^D|^X,有的同窗寫成^D|X這樣是錯誤的。

示例5:顯示全部ID號碼最後一位數字是1或5的人的全名

[root@chensiqi1 files]# cat reg.txt 
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ :]+" '$3~/1$|5$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

示例6:顯示Xiaoyu的捐款,每一個值都有以$開頭。如$520$200$135

[root@chensiqi1 files]# cat reg.txt 
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ :]+" '$2~/Xiaoyu/{print "$"$4"$"$5"$"$6}' reg.txt 
$155$90$201

示例7:顯示全部人的全名,以姓,名的格式顯示,如Meng,Feixue

[root@chensiqi1 files]# cat reg.txt 
Zhang Dandan    41117397    :250:100:175
Zhang Xiaoyu    390320151   :155:90:201
Meng  Feixue    80042789    :250:60:50
Wu    Waiwai    70271111    :250:80:75
Liu   Bingbing  41117483    :250:100:175
Wang  Xiaoai    3515064655  :50:95:135
Zi    Gege      1986787350  :250:168:200
Li    Youjiu    918391635   :175:75:300
Lao   Nanhai    918391635   :250:100:175
[root@chensiqi1 files]# awk -F "[ ]+" '{print $1","$2}' reg.txt 
Zhang,Dandan
Zhang,Xiaoyu
Meng,Feixue
Wu,Waiwai
Liu,Bingbing
Wang,Xiaoai
Zi,Gege
Li,Youjiu
Lao,Nanhai

2.2.9 企業面試題:取出網卡eth0的ip地址

最簡單:hostname -I

awk處理:

方法一:

[root@chensiqi1 files]# ifconfig eth0|awk 'BEGIN{RS="[ :]"}NR==31'
192.168.197.133

方法二:

[root@chensiqi1 files]# ifconfig eth0 | awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}'
192.168.197.133

方法三:

[root@chensiqi1 files]# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}'
192.168.197.133

方法四:

[root@chensiqi1 files]# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}'
192.168.197.133

提示:

  • 前邊的三種方法都仍是比較好理解的,這第四種方法,須要學會逆向思惟,看看咱們要的結果10.0.0.50,ip地址:數字和點(.),我是否能夠指定分隔符,以數字和點之外的字符爲分隔符呢?
  • 換句話說就是要排除數字和點(.)正則表達式與排除經常使用的就是[^0-9.]即不匹配數字和點(.)
  • 最後-F 「[^0-9]」位分隔符,可是要使用+,表示連續的。合起來就是:awk -F 「[^0-9.]+」 'NR==2{print $2}'

注意:
正則表達式是玩好awk的必要條件,必會掌握

2.2.10 明明白白擴展正則表達式:+(加號)

[root@chensiqi1 files]# echo "------======1########2"
------======1########2
[root@chensiqi1 files]# echo "------======1########2" | grep "[-=#]"
------======1########2
[root@chensiqi1 files]# echo "------======1########2" | grep -o "[-=#]"
-
-
-
-
-
-
=
=
=
=
=
=
#
#
#
#
#
#
#
#

2.2.11 awk正則之{} -花括號

awk中的花括號有些不經常使用,可是偶爾會用到這裏簡單介紹。

示例:取出awkfile中第一列包含一個o或者兩個o的行

[root@chensiqi1 files]# awk -F: '$1~/o{1,2}/' awkfile.txt 
[root@chensiqi1 files]# awk -F: --posix '$1~/o{1,2}/' awkfile.txt 
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@chensiqi1 files]# awk -F: --re-interval '$1~/o{1,2}/' awkfile.txt 
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

2.2.12 企業案例1:取出經常使用服務端口號

思路:
linux下面服務與端口信息的對應表格在/etc/services裏面,因此這道題要處理/etc/services文件。

咱們簡單分析如下servics文件:

[root@chensiqi1 ~]# sed -n '23,30p' /etc/services
tcpmux          1/tcp                           # TCP port service multiplexer
tcpmux          1/udp                           # TCP port service multiplexer
rje             5/tcp                           # Remote Job Entry
rje             5/udp                           # Remote Job Entry
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null
discard         9/udp           sink null

從23行開始基本上每一行第一列是服務名稱,第二列的第一部分是端口號,第二列的第二部分是tcp或udp協議。

方法:

[root@chensiqi1 ~]# awk -F "[ /]+" '$1~/^(ssh)$|^(http)$|^(https)$|^(mysql)$|^(ftp)$/{print $1,$2}' /etc/services |sort|uniq
ftp 21
http 80
https 443
mysql 3306
ssh 22

提示:

  • |是或者的意思,正則表達式
  • sort是將輸出結果排序
  • uniq是去重複但不標記重複個數
  • uniq -c去重複但標記重複個數

2.2.13 企業案例2:取出經常使用服務端名稱

同窗們本身嘗試下

2.3 比較表達式作爲模式-須要一些例子

以前咱們看了正則表達式在awk下的運用,下面再具體看看比較表達式如何在awk下工做。

awk是一種編程語言,可以進行更爲複雜的判斷,當條件爲真時候,awk就執行相關的action。主要是針對某一區域作出相關的判斷,好比打印成績在80分以上的行,這樣就必須對這一區域作比較判斷,下表列出了awk可使用的關係運算符,能夠用來比較數字字符串,還有正則表達式。當表達式爲真時候,表達式結果1,否0,只有表達式爲真,awk才執行相關的action

運算符 含義 示例
< 小於 x>y
<= 小於等於 x<=y
== 等於 x==y
!= 不等於 x!=y
>= 大於或等於 x>=y
> 大於 x<y

以上運算符是針對數字的,下面兩個運算符以前已有示例,針對字符串

~ 與正則表達式匹配 x~/y/
!~ 與正則表達式不匹配 x!~y

2.3.1 企業面試題:取出文件/etc/services的23~30行

思路:
想表示一個範圍,一個行的範圍,就要用到NR這個內置變量了,同時也要用到比較表達式。

答案:

[root@www ~]# awk 'NR>=23&&NR<=30' /etc/services
[root@www ~]# awk 'NR>22&&NR<31' /etc/services

過程:

[root@www ~]# awk 'NR>=23&&NR<=30' /etc/services
tcpmux          1/tcp                           # TCP port service multiplexer
tcpmux          1/udp                           # TCP port service multiplexer
rje             5/tcp                           # Remote Job Entry
rje             5/udp                           # Remote Job Entry
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null
discard         9/udp           sink null
[root@www ~]# awk 'NR>22&&NR<31' /etc/services
tcpmux          1/tcp                           # TCP port service multiplexer
tcpmux          1/udp                           # TCP port service multiplexer
rje             5/tcp                           # Remote Job Entry
rje             5/udp                           # Remote Job Entry
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null
discard         9/udp           sink null

說明:
1)比較表達式比較經常使用的仍是表示大於等於,小於等於或者等於,根據這個例子來學習便可
2)NR表示行號,大於等於23即,NR>=23小於等於30,即NR<=30
3)合起來就是NR>=23而且NR<=30,&&表示而且,同時成立的意思。
4)換一種表達式方法就是大於22行小於31行,即NR>22&&NR<31

2.3.2 若是判斷某一列是否等於某個字符呢?

示例:找出/etc/passwd中第五列是root的行

測試文件:

[root@www ~]# cat /server/files/awk_equal.txt
root:x:0:0:root:/root:/bin/bash
root:x:0:0:rootroot:/root:/bin/bash
root:x:0:0:rootrooot:/root:/bin/bash
root:x:0:0:rootrooot:/root:/bin/bash
root:x:0:0:/root:/bin/bash

答案:

awk -F":" '$5=="root"' /server/files/awk_equal.txt 
awk -F":" '$5~/^root$/' /server/files/awk_equal.txt

過程:

#方法一:
[root@www ~]# awk -F":" '$5=="root"' /server/files/awk_equal.txt 
root:x:0:0:root:/root:/bin/bash
#方法二:
[root@www ~]# awk -F":" '$5~/^root$/' /server/files/awk_equal.txt 
root:x:0:0:root:/root:/bin/bash

咱們若是想要徹底匹配root這個字符串,那就用$5=="root"便可,這也是答案裏面給你們的。

方法二:
此題也可經過正則匹配來限制root的字符串。$5~/^root$/

2.4 範圍模式

pattern1 pattern2
從哪裏來 哪裏去
條件1 條件2
  • 範圍模式簡單理解就是從哪裏來,到哪裏去。
  • 匹配從條件1開始到條件2介紹的範圍

1)還記得sed使用地址範圍來處理文本內容嘛?awk的範圍模式,與sed相似,可是又有不一樣,awk不能直接使用行號來做爲範圍起始地址,由於awk具備內置變量NR來存儲記錄號,全部須要使用NR=1,NR=5這樣來使用。
2)範圍模式處理的原則是:先匹配從第一個模式的首次出現到第二個模式的首次出現之間的內容,執行action。而後匹配從第一個模式的下一次出現到第二個模式的下一次出現,直到文本結束。若是匹配到第一個模式而沒有匹配到第二個模式,則awk處理從第一個模式開始直到文本結束所有的行。若是第一個模式不匹配,就算第二個模式匹配,awk依舊不處理任何行。

awk '/start pos/,/end pos/{print $)} passwd chensiqi'
awk '/start pos/,NR==XXX{print $0}' passwd chensiqi

範圍模式的時候,範圍條件的時候,表達式必須能匹配一行。

示例1:

[root@www files]# awk 'NR==2,NR==5{print NR,$0}' count.txt 
2 bin x bin bin sbin nologin
3 daemon x daemon sbin sbin nologin
4 adm x adm var adm sbin nologin
5 lp x lp var spool lpd sbin nologin

說明:
條件是:從第二行,到第五行
動做是:顯示行號(NR)和整行($0)
合起來就是顯示第二行到第五行的行好和整行的內容

示例2:

[root@www files]# awk '/^bin/,NR==5{print NR,$0}' awkfile.txt 
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

說明:
條件是:從以bin開頭的行,到第五行
動做是:顯示行號和整行內容
合起來就是顯示從以bin開頭的行,到第五行中的行號和整行內容。

示例3:

[root@www files]# awk -F":" '$5~/^bin/,/^lp/{print NR,$0}' awkfile.txt
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

說明:
條件:從第五列以bin開頭的行到以lp開頭的行
動做:顯示行號和正航內容
合起來:從第三列以bin開始的行到以lp開頭的行並顯示其行號和整行內容

[root@www files]# awk -F: '$5~/^bin/,$5~/^lp/{print NR,$0}' awkfile.txt 
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

說明:
條件:從第三列以bin開頭字符串的行到第三列以lp開頭字符串的行
動做:顯示行號和整行

2.5 awk特殊模式-BEGIN模式與END模式

  • BEGIN模塊再awk讀取文件以前就執行,通常用來定義咱們的內置變量(預約義變量,eg:FS,RS),能夠輸出表頭(相似excel表格名稱)
  • BEGIN模式以前咱們有在示例中提到,自定義變量,給內容變量賦值等,都使用過。須要注意的是BEGIN模式後面要接跟一個action操做塊,包含在大括號內。awk必須在輸入文件進行任何處理前先執行BEGIN裏的動做(action)。咱們能夠不要任何輸入文件,就能夠對BEGIN模塊進行測試,由於awk須要先執行完BEGIN模式,纔對輸入文件作處理。BEGIN模式經常被用來修改內置變量ORS,RS,FS,OFS等值。

2.5.1 BEGIN模塊

1)第一個做用,內置變量的定義

示例:取eth0的IP地址

答案:

[root@www files]# ifconfig eth0|awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}'
192.168.197.133 
[root@www files]# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}'
192.168.197.133
[root@www files]# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}'
192.168.197.133

#上面的也能夠寫成
[root@www files]# ifconfig eth0 | awk 'BEGIN{FS="(addr:)|( Bcast:)"} NR==2{print $2}'
192.168.197.133 
[root@www files]# ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'
192.168.197.133
[root@www files]# ifconfig eth0 | awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}'
192.168.197.133

注意:
命令行-F本質就是修改的FS變量

2)第二個做用,在讀取文件以前,輸出些提示性信息(表頭)。

[root@www files]# awk -F: 'BEGIN{print "username","UID"}{print $1,$3}' awkfile.txt 
username UID   #這就是輸出的表頭信息
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
uucp 10

說明:
要在第一行輸出一些username和UID,咱們應該想到BEGIN{}這個特殊的條件(模式),由於BEGIN{}在awk讀取文件以前執行的。
因此結果是BEGIN{print "username","UID"},注意print命令裏面雙引號吃啥吐啥,原樣輸出。
而後咱們實現了在輸出文件內容以前輸出「username」和「UID」,下一步輸出文件的第一列和第三列即{print $1,$3}
最後結果就是BEGIN{print "username","UID"}{print $1,$3}

3)第三個做用,使用BEGIN模塊的特殊性質,進行一些測試。

[root@www files]#簡單輸出內容:
[root@www files]# awk 'BEGIN{print "hello world!"}'
hello world!
[root@www files]# #進行計算
[root@www files]# awk 'BEGIN{print 10/3}'
3.33333
[root@www files]# awk 'BEGIN{print 10/3+1}'
4.33333
[root@www files]# awk 'BEGIN{print 10/3+1/4*9}'
5.58333
[root@www files]# #和變量有關的操做
[root@www files]# awk 'BEGIN{a=1;b=2;print a,b}'
1 2
[root@www files]# awk 'BEGIN{a=1;b=2;print a,b,a+b}'
1 2 3

4)第四種用法:配合getline讀取文件,後面awk函數處講解

2.5.2 awk中變量的概念簡介

  • 直接定義,直接使用便可
  • awk中字母會被認爲是變量,若是真的要給一個變量賦值字母(字符串),請使用雙引號
[root@chensiqi files]# awk 'BEGIN{a=abcd;print a}'

[root@chensiqi files]# awk 'BEGIN{abcd=123456;a=abcd;print a}'
123456
[root@chensiqi files]# awk 'BEGIN{a="abcd";print a}'
abcd

說明:
沒有文件awk依舊能夠處理BEGIN模式下的動做(命令)

2.5.3 END模塊

EHD在awk讀取完全部的文件的時候,再執行END模塊,通常用來輸出一個結果(累加,數組結果),也能夠是和BEGIN模塊相似的結尾標識信息

[root@chensiqi files]# awk 'BEGIN{print "hello world!"}{print NR,$0}END{print "end of file"}' count.txt 
hello world!
1 root x root root bin bash
2 bin x bin bin sbin nologin
3 daemon x daemon sbin sbin nologin
4 adm x adm var adm sbin nologin
5 lp x lp var spool lpd sbin nologin
6 sync x sync sbin bin sync
7 shutdown x shutdown sbin sbin shutdown
8 halt x halt sbin sbin halt
9 mail x mail var spool mail sbin nologin
10 uucp x uucp var spool uucp sbin nologin
end of file

與BEGIN模式相對應的END模式,格式同樣,可是END模式僅在awk處理完全部輸入行後才進行處理。

企業案例:統計/etc/servies文件裏的空行數量

思路:
a)空行經過正則表達式來實現:^$
b)統計數量:

  • grep -c
  • awk

方法一:grep

[root@chensiqi files]# grep "^$" /etc/services | wc -l
16
[root@chensiqi files]# grep -c "^$" /etc/services
16

說明:
grep命令-c表示count計數統計包含^$的行一共有多少。

方法二:

[root@chensiqi files]# awk '/^$/{i++}END{print i}' /etc/services 
16

提示:
使用了awk的技術功能,很經常使用
第一步:統計空行個數
/^$/表示條件,匹配出空行,而後執行{i++}(i++等於i=i+1)即:/^$/{i=i+1}

咱們能夠經過/^$/{i=i+1;print i}來查看awk執行過程

[root@chensiqi files]# awk '/^$/{i=i+1;print "the value of i is:"i}' /etc/services 
the value of i is:1
the value of i is:2
the value of i is:3
the value of i is:4
the value of i is:5
the value of i is:6
the value of i is:7
the value of i is:8
the value of i is:9
the value of i is:10
the value of i is:11
the value of i is:12
the value of i is:13
the value of i is:14
the value of i is:15
the value of i is:16

第二步:輸出最後結果

  • 可是咱們只想要最後的結果16,不想要過程怎麼辦?使用END模式輸出結果
  • 由於END模式的特殊性質因此很適合輸出最終結果

因此最終結果就是awk '/^$/{i=i+1}END{print "blank lines count:"i}' /etc/services

awk編程思想:

  1. 先處理,最後再END模塊輸出
  2. {print NR,$0}body模塊處理,處理完畢後
  3. END{print "end of file"}輸出一個結果

企業面試題5:文件count.txt,文件內容是1到100(由seq 100生成),請計算文件每行值加起來的結果(計算1+...+100)

思路:
文件每一行都有且只有一個數字,因此咱們要讓文件的每行內容相加。
回顧一下上一道題咱們用的是i++即i=i+1
這裏咱們須要使用到第二個經常使用的表達式
i=i+$0

對比一下,其實只是把上邊的1換成了$0

[root@chensiqi files]# awk '{i=i+$0}END{print i}' count.txt 
5050

2.6 awk中的動做

在一個模式-動做語句中,模式決定動做何時執行,有時候動做會很是簡單:一條單獨的打印或賦值語句。在有些時候,動做有多是多條語句,語句之間用換行符或分號分開。
awk的動做中若是有兩個或兩個以上的語句,須要用分號分隔
動做部分你們理解爲花括號裏面的內容便可,整體分爲:

  • 表達式
  • 流程控制語句
  • 空語句
  • 數組(之後若是有時間的話會再寫一個awk高級部分進行介紹)

2.7 awk模式與動做小結

  • awk命令核心由模式和動做組成
  • 模式就是條件,動做就是具體幹什麼
    1)正則表達式:必須掌握正則,熟練
    2)條件表達式:比大小,比較是否相等
    3)範圍表達式:從哪裏來到哪裏去
  • 注意BEGIN或END模塊只能有一個。BEGIN{}BEGIN{}或者END{}END{}都是錯誤的。

2.8 總結awk執行過程

回顧一下awk的結構

awk -F 指定分隔符 ‘BRGIN{}END{}’,以下圖

屏幕快照 2017-02-28 下午8.26.57.png-734kB

#awk完整執行過程
[root@chensiqi ~]# awk -F ":" 'BEGIN{RS="/";print "hello world!"}{print NR,$0}END{print "end of file"}' /server/files/awkfile.txt 
hello world!
1 root:x:0:0:root:
2 root:
3 bin
4 bash
bin:x:1:1:bin:
5 bin:
6 sbin
7 nologin
daemon:x:2:2:daemon:
8 sbin:
9 sbin
10 nologin
adm:x:3:4:adm:
11 var
12 adm:
13 sbin
14 nologin
lp:x:4:7:lp:
15 var
16 spool
17 lpd:
18 sbin
19 nologin
sync:x:5:0:sync:
20 sbin:
21 bin
22 sync
shutdown:x:6:0:shutdown:
23 sbin:
24 sbin
25 shutdown
halt:x:7:0:halt:
26 sbin:
27 sbin
28 halt
mail:x:8:12:mail:
29 var
30 spool
31 mail:
32 sbin
33 nologin
uucp:x:10:14:uucp:
34 var
35 spool
36 uucp:
37 sbin
38 nologin

end of file

說明:
咱們·同時再命令行定義了分隔符和在BEGIN模式中定義了RS內置變量,在最後經過END模式輸出告終果

2.9 awk數組

awk提供了數組來存放一組相關的值。
awk是一種編程語言,確定也支持數組的運用,可是又不一樣於c語言的數組。數組在awk中被稱爲關聯數組,由於它的下標既能夠是數字也能夠是字符串。下標一般被稱做key,而且與對應的數組元素的值關聯。數組元素的key和值都存儲在awk程序內部的一張表中,經過必定散列算法來存儲,因此數組元素都不是按順序存儲的。打印出來的順序也確定不是按照必定的順序,可是咱們能夠經過管道來對所需的數據再次操做來達到本身的效果。

屏幕快照 2017-02-28 下午9.48.36.png-342.6kB

如圖不難發現,awk數組就和酒店同樣。數組的名稱就像是酒店名稱,數組元素名稱就像酒店房間號碼,每一個數組元素裏面的內容就像是酒店房間裏面的人。

2.10 圖片-數組

假設咱們有一個酒店

酒店<===>chensiqihotel

酒店裏面有幾個房間110,119,120,114這幾個房間

酒店110房間<===>chensiqihotel[110]
酒店120房間<===>chensiqihotel[120]
酒店119房間<===>chensiqihotel[119]
酒店114房間<===>chensiqihotel[114]

酒店房間裏面入住客人

酒店110房間住着xiaoyu<===>chensiqihotel[110]="xiaoyu"
酒店119房間住着ruxue<===>chensiqihotel[119]="ruxue"
酒店120房間住着dandan<===>chensiqihotel[120]="dandan"
酒店114房間住着waiwai<===>chensiqihotel[114]="waiwai"

示例:

[root@chensiqi ~]# awk 'BEGIN{chensiqihotel[110]="xiaoyu";chensiqihotel[119]="ruxue";chensiqihotel[120]="dandan";chensiqihotel[114]="waiwai";print chensiqihotel[110],chensiqihotel[119],chensiqihotel[120],chensiqihotel[114]}'
xiaoyu ruxue dandan waiwai
[root@chensiqi ~]# awk 'BEGIN{chensiqihotel[110]="xiaoyu";chensiqihotel[119]="ruxue";chensiqihotel[120]="dandan";chensiqihotel[114]="waiwai";for(hotel in chensiqihotel)print hotel,chensiqihotel[hotel]}'
110 xiaoyu
120 dandan
114 waiwai
119 ruxue

企業面試題1:統計域名訪問次數

處理如下文件內容,將域名取出並根據域名進行計數排序處理:(百度和sohu面試題)

http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html

思路:
1)以斜線爲菜刀取出第二列(域名)
2)建立一個數組
3)把第二列(域名)做爲數組的下標
4)經過相似於i++的形式進行計數
5)統計後把結果輸出

過程演示:
第一步:查看一下內容

[root@chensiqi ~]# awk -F "[/]+" '{print $2}' file 
www.etiantian.org
www.etiantian.org
post.etiantian.org
mp3.etiantian.org
www.etiantian.org
post.etiantian.org

命令說明:
這是咱們須要計數的內容

第二步:計數

[root@chensiqi ~]# awk -F "[/]+" '{i++;print $2,i}' file 
www.etiantian.org 1
www.etiantian.org 2
post.etiantian.org 3
mp3.etiantian.org 4
www.etiantian.org 5
post.etiantian.org 6

命令說明:
i++:i最開始是空的,當awk讀取一行,i自身+1

第三步:用數組替換i

[root@chensiqi ~]# awk -F "[/]+" '{h[$2]++;print $2,h["www.etiantian.org"]}' file 
www.etiantian.org 1
www.etiantian.org 2
post.etiantian.org 2
mp3.etiantian.org 2
www.etiantian.org 3
post.etiantian.org 3

命令說明:
1)將i替換成h[$2];至關於我建立了一個數組h[],而後用$2做爲個人房間號。可是目前房間裏是沒有東西的。也就是說h[$2]=h["www.etiantian.org"] and h["post.etiantian.org"] and h["mp3.etiantian.org"] 可是具體房間裏是沒有東西的也就是空。
2)h[$2]++就等於i++:也就是說我開始給房間里加東西;當出現一樣的東西,我就++
3)print h["www.etiantian.org"]:意思就是說我開始要輸出了。我要輸出的是房間號爲「www.etiantian.org」裏面的內容。這裏面的內容最先是空的,隨着awk讀取每一行一旦出現房間號爲「www.etiantian.org」的房間時,我就給房間裏的內容進行++。
4)綜上,輸出的結果中,每次出現www.etiantian.org時,h["www.etiantian.org"]就會++。所以最後的輸出數字是3

第四步:輸出最終計數結果

[root@chensiqi ~]# awk -F "[/]+" '{h[$2]++}END{for(i in h)print i,h[i]}' file 
mp3.etiantian.org 1
post.etiantian.org 2
www.etiantian.org 3
[root@chensiqi ~]# 

命令說明:
咱們最終須要輸出的是去重複之後的統計結果,因此得在END模塊裏進行輸出
for(i in h)遍歷這個數組,i裏存的都是房間號
print i,h[i]:輸出每個房間號及其房間裏的內容(計數結果)

提示: awk的應用裏最重要的一個功能就是計數,而數組在awk裏最大的做用就是去重複。請同窗們仔細理解,多動手試驗一下。

相關文章
相關標籤/搜索