awk腳本語言編程指南

AWK入門指南html

安裝AWK

# 使用yum安裝
yum install gawk
 # 安裝後檢查是否安裝ok
which awk
## 通常輸出安裝路徑是在: /bin/awk
複製代碼

AWK 起步示例

假設存在一個文件 emp.data,其中包含員工的姓名、薪資(美圓/小時)以及小時數,一個員工一行數據,其內容以下:node

Beth	4.00	0
Dan	3.75	0
kathy	4.00	10
Mark	5.00	20
Mary	5.50	22
Susie	4.25	18
複製代碼

若是想打印出 工做時長超過0小時的員工姓名和工資(薪資乘以時間),如下命令能夠完成:linux

awk '$3>0 {print $1, $2*$3}'  emp.data

複製代碼

獲得以下輸出:正則表達式

kathy 40
Mark 100
Mary 121
Susie 76.5
複製代碼

該命令告訴系統執行括號內的awk程序,從輸入文件 emp.data 獲取所須要的數據。引號內的部分是個完整的awk程序,包含單個 模式-動做 語句。模式 $3>0 用於匹配第三列大於0的輸入行,動做: {print $1, $2*$3} 打印每一個匹配行的第一個字段、第二個字段與第三個字段的乘積。redis

還能夠打印沒有工做過的員工姓名:shell

awk '$3==0 {print $1}'  emp.data
複製代碼

將會輸出:編程

Beth
Dan
複製代碼

AWK程序的結構

回過頭來看一下上述命令。引號之間的部分是awk編程語言寫就的程序。 每一個awk程序都是 一個或多個 模式-動做 語句的序列:數組

pattern {pattern} pattern {pattern} ...bash

awk 的基本操做是一行一行的掃描輸入,搜索匹配任意程序中模式的行。 詞語「匹配」的準確意義是視具體的模式而言,對於模式 $3>0 來講,意思是「條件爲真」。 每一個模式依次測試每一個輸入行。對於匹配到行的模式,其對應的動做(也許包含多步)獲得執行,而後讀取下一行並繼續匹配,直到全部的輸入讀取完畢。服務器

模式 動做
$3==0 {print $1}

模式-動做 語句中的 模式或動做(但不是二者同時省略)均可以省略。若是某個模式沒有動做,例如:

$3==0

那麼模式匹配到的每一行都會被打出來。輸出以下:

Beth    4.00    0
Dan     3.75    0
複製代碼

若是是沒有動做的模式,例如: {print $1} 則會打印第一列,輸出以下:

Beth
Dan
kathy
Mark
Mary
Susie
複製代碼

因爲模式和動做二者任一都是可選的,因此須要使用大括號包圍動做用以區分其餘模式。

執行 awk 程序

執行awk程序有多種,能夠輸入以下形式的命令行: awk 'program codes' inputfiles 從而在每一個指定的輸入文件上執行這個program。例如: awk '$3==0 {print $1}' file1 file2 打印 file1 和 file2 文件中第三列爲0的每一行的第一個字段。

也能夠省略命令行中的輸入文件,僅僅輸入: awk 'program codes' 在這種狀況下,awk 將會應用於你在終端接着輸入的任意數據行,直到你輸入一個文件結束信號(Unix系統上爲control-d)。示例:

awk '$3>0 {print $1}'
Mary 20 1000   #輸入該行回車
Mary  # 計算機輸出,匹配到了信息
Belly 30 3000  #繼續輸入改行
Belly #計算機輸出
複製代碼

注意事項: 命令行中的程序是用單引號包圍着的。這會防止shell解釋程序中$這樣的字符,也容許程序的長度超過一行。 當程序比較長的時候,能夠將程序寫入到一個文件,如下命令行: awk -f programfile optional list of input files

其中 -f 選項指示 awk 從指定文件中獲取程序。可使用任意文件名替換 programfile。

awk 的錯誤提示

若是你的 awk 程序存在錯誤, awk 會給你一些診斷信息。例如,若是你打錯了大括號,以下所示:

awk '$3==0 [print $1}' emp.data 會提示以下錯誤:

awk: $3==0 [print $1}
awk:       ^ syntax error
awk: $3==0 [print $1}
awk:                ^ syntax error
複製代碼

簡單輸出

awk中僅僅只有兩種類型 數值字符 構成的字符串。一般狀況下,一個字段是一個不包含任何空格或製表符的連續字符序列。 當前輸入的 行中的第一個字段被稱做 $1,第二個是 $2,以此類推。 整個行的內容被定義爲 $0。 每一行的字段數量能夠不一樣。

大都數狀況下,咱們僅僅只是打印出其中每一行的某些字段,或者也還須要作一些計算。

打印每一行

若是一個動做沒有任何模式,這個動做針對全部輸入的行進行操做。 print 語句用來打印(輸出)當前輸入的行。 因此 {print} 等效於 {print $0}

打印特定行

{print $1,$3} 將輸出:

Beth 0
Dan 0
kathy 10
Mark 20
Mary 22
Susie 18
複製代碼

在 print 語句中被逗號分隔的表達式,在默認狀況下他們將會用一個空格分割來輸出。 每一行print生成的內容都會以一個換行符做爲結束。但這些默認行爲均可以自定義。

NF,字段數量

AWK 會對當前輸入的行有多少字段進行計數,而且將當前行的字段數量存儲在一個內建的稱爲 NF 的變量中。所以 {print NF,$1,$NF} 會打印出 每一行的字段數量、第一個字段的值、最後一個字段的值。 輸出:

3 Beth 0
3 Dan 0
3 kathy 10
3 Mark 20
3 Mary 22
3 Susie 18
複製代碼

打印行號

awk 提供了另外一個內建變量, NR。他存儲了當前已經讀取了多少行的計數。可使用 NR和$0給emp.data的每一行加上行號: {print NR,$0} 輸出以下:

1 Beth  4.00    0
2 Dan   3.75    0
3 kathy 4.00    10
4 Mark  5.00    20
5 Mary  5.50    22
6 Susie 4.25    18
複製代碼

在輸出中添加內容

還能夠在字段中間或者計算的值中間打印輸出想要的內容: {print "total pay for", $1, "is", $2*$3} 輸出以下:

total pay for Beth is 0
total pay for Dan is 0
total pay for kathy is 40
total pay for Mark is 100
total pay for Mary is 121
total pay for Susie is 76.5
複製代碼

高級輸出

print 語句可用於快速而簡單的輸出。若要嚴格按照你所想的格式化輸出,則須要使用 printf 語句。

字段排隊

printf 語句格式以下:

printf(format, value1, value2, ..., valueN)

其中 format 是字符串,包含要逐字打印的文本,穿插在 format 以後的每一個值該如何打印的規格。一個規格是一個 % 符,後面跟着一些字符,用來控制一個 value 的格式。所以,有過少個 value 要打印,在 fromat 中就要有多少個 % 規格。 打印每一個員工的總薪酬: {printf("total pay for %s is $%.2f\n", $1, $2*$3)} 輸出以下:

awk '{printf("total pay for %s is $%.2f\n", $1, $2*$3)}'  emp.data
total pay for Beth is $0.00
total pay for Dan is $0.00
total pay for kathy is $40.00
total pay for Mark is $100.00
total pay for Mary is $121.00
total pay for Susie is $76.50
複製代碼

排序輸出

以薪酬遞增的方式輸出每一行:

awk '{printf("%6.2f %s\n", $2*$3, $0)}' emp.data | sort

將awk的輸出經過管道傳給 **sort **命令,輸出以下:

0.00  Beth    4.00    0
  0.00  Dan     3.75    0
100.00  Mark    5.00    20
121.00  Mary    5.50    22
 40.00  kathy   4.00    10
 76.50  Susie   4.25    18
複製代碼

選擇

awk 的模式適用於爲進一步的處理從輸入中選擇相關的數據行。因爲不帶動做的模式會打印全部匹配的行,因此不少awk程序僅僅包含一個模式。本節將給出一些有用的模式示例。

經過對比選擇

使用一個對比模式來選擇每小時賺5美圓或更多的員工記錄,亦即第二個字段大於等於5的行: $2>=5

awk '$2>=5'  emp.data
Mark    5.00    20
Mary    5.50    22
複製代碼

經過計算選擇

awk '$2*$3>50 {printf("$%.2f for %s\n", $2*$3, $1)}'  emp.data
$100.00 for Mark
$121.00 for Mary
$76.50 for Susie
複製代碼

經過文本內容選擇

除了數值測試,還能夠選擇包含特定單詞或短語的輸入行。這個程序會打印全部第一個字段爲 Susie 的行:

$1=="Susie"

操做符 == 用於測試相等性。 也可使用正則表達式的模式查找包含任意任意字母組合,單詞或短語的文本。如如下能夠匹配到任意位置包含Susie的行: /Susie/

awk '/Susie/'  emp.data
Susie   4.25    18
複製代碼

模式組合

可使用括號和邏輯操做符號與&&、或||,以及 非! 對模式進行組合。 $2>=4||$3>=20 會打印第二個字段大於等於4或者第三個字段大於等於20的行:

awk '$2>=4||$3>=20'  emp.data
Beth    4.00    0
kathy   4.00    10
Mark    5.00    20
Mary    5.50    22
Susie   4.25    18
複製代碼

BEGIN 與 END

特殊模式 BEGIN 用於匹配第一個輸入文件的第一行以前的位置。END 則用於匹配處理過的最後一個文件的最後一行的位置。

這個程序使用 BEGIN 來輸出一個標題:

BEGIN {print "Name RATE HOURS"; print ""}
    {print}
複製代碼
awk 'BEGIN {print "Name RATE HOURS"; print ""}
{print}' emp.data
 ## 輸出以下:

Name RATE HOURS

Beth    4.00    0
Dan     3.75    0
kathy   4.00    10
Mark    5.00    20
Mary    5.50    22
Susie   4.25    18
複製代碼

注意事項:

  • awk 能夠在一行上放多個語句,步過要使用分號;進行分隔。

  • 普通的 print 是打印當前輸入行, print "" 則會打印一個空行。

AWK 工做流圖

Awk 工做流圖

AWK 是按一行一行地讀取輸入的。

  • 1.首先執行 BEGIN
  • 2.從輸入中讀取一行
  • 3.在此次讀取的這一行中執行 AWK 命令
  • 4.若是文件尚未讀取完畢,則重複步驟二、3
  • 5.執行 END 塊中的 awk 命令

使用 AWK 進行計算

一個動做就是一個以新行或者分號分隔的語句序列。

計數
$3 > 15 {emp = emp + 1}
END {print emp, "employees worked more than 15 hours"}
複製代碼
awk '$3 > 15 {emp = emp + 1}
> END {print emp, "employees worked more than 15 hours"}' emp.data
 ## 輸出結果:
3 employees worked more than 15 hours
複製代碼

用做數字的 awk 變量的默認初始值爲0, 因此不須要初始化 emp。建立一個變量emp初始值爲0,若是讀入的那一行的第三個字段大於15,則emp在自身值的基礎上自增1,讀完最後一行後輸出存在多少個員工工做時長超過15個小時的語句。

求和與平均值

爲計算員工數目,可使用內置變量 NR,保存了當前位置讀取的行數;在全部輸入的結尾它的值就是所讀行的總行數。

END {print NR, "employees"}

awk 'END {print NR, "employees"}'  emp.data
 ## 輸出結果爲:
6 employees
複製代碼

以下是一個使用 NR 來計算薪酬均值的程序:

awk '{pay = pay + $2*$3}
> END {print NR, "employees"
> print "total pay is", pay
> print "average pay is", pay/NR
> }' emp.data
 ## 輸出結果爲:
6 employees
total pay is 337.5
average pay is 56.25
複製代碼

處理文本

awk 的優點之一是能像大多數語言處理數字同樣方便地處理字符串。 awk 能夠保存數字也能夠保存字符。找出時薪最高的員工:

$2 > maxrate { maxrate = $2; maxemp = $1 }
END { print "highest hourly rate:", maxrate, "for", maxemp }
複製代碼
awk '$2 > maxrate { maxrate = $2; maxemp = $1 }
> END { print "highest hourly rate:", maxrate, "for", maxemp }' emp.data
 ## 輸出結果爲:
highest hourly rate: 5.50 for Mary
複製代碼
awk '{names = names $1 " "}                    
END {print names}' emp.data
 ## 輸出結果:
Beth Dan kathy Mark Mary Susie 
複製代碼

打印最後一個輸入行

雖然在 END 動做中 NR 還保留着它的值, 但 $0 沒有。

{last = $0}
END {print last}
複製代碼
awk '
> {last = $0}
> END {print last}' emp.data
 ## 輸出結果:
Susie   4.25    18
複製代碼

AWK 內置函數

前面已經看到 awk 內置變量用來保存某些頻繁使用的數量, NF 表示所在行的總列數, NR 表示當前是第多少行... 還有內置函數用來計算其餘有用的數值。除了 平方根、對數、隨機數此類的算術函數外,還有操做文本的函數。其中之一是 length 用於計算一個字符串的長度。

awk '{print $1, length($1)}'  emp.data
 ## 輸出結果:
Beth 4
Dan 3
kathy 5
Mark 4
Mary 4
Susie 5
複製代碼

行、單詞以及字符的計數

使用 length、NF、NR來統計輸入中行、單詞以及字符的數量。爲了簡便,將每一個字段看做一個單詞。

awk ' { nc = nc + length($0) + 1
> nw = nw + NF
> }
> END { print NR, "lines,", nw, "words,", nc, "characters" }' emp.data
 ## 輸出結果爲:
6 lines, 18 words, 82 characters
複製代碼

由於 $0 不會包含行末的換行符,因此另外加了個1。

AWK 控制語句

awk 爲選擇提供了一個 if-else 語句, 以及爲循環提供了幾個語句,它們僅在動做中使用。

if-else 語句

以下是一個計算時薪超過6美圓的員工總薪酬與平均薪酬。它使用一個 if 來防範零除問題。

$2 > 6 { n = n+1; pay = pay + $2*$3 }
END {
    if(n > 0)
        print n, "employees, total pay is", pay,
               "average pay is", pay/n
    else
        print "no employees are paid more than $6/hour"
        
}

複製代碼
awk '$2 > 6 { n = n+1; pay = pay + $2*$3 }
> END {
> if(n > 0)
> print n, "employees, total pay is", pay,
> "average pay is", pay/n
> else
> print "no employees are paid more than $6/hour"
> 
> }' emp.data
 ## 輸出結果爲:
no employees are paid more than $6/hour
複製代碼

注意事項: 咱們可使用一個逗號將一個長語句截斷爲多行來書寫.

while 語句
{
    i = 1
    while ( i <=3 ){
        # while 循環體(這一行是註釋內容)
        printf("\t%.2f\n", $1*(1+$2)^i)
        i = i + 1
    }
}
複製代碼

while 後面是圓括號,裏面是布爾表達式。 循環體是條件後大括號包圍的語句。 ^ 是指數操做符。 # 後面是註釋。

演示1000美圓,利率爲6%與12%,5年的複利分別是如何增加的:

awk ' > { > i = 1 > while ( i <=5 ){ > # while 循環體(這一行是註釋內容) > printf("\t%.2f\n", $1*(1+$2)^i) > i = i + 1 > } > } > ' 
1000 .06 5
        1060.00
        1123.60
        1191.02
        1262.48
        1338.23
1000 .12 5
        1120.00
        1254.40
        1404.93
        1573.52
        1762.34
複製代碼
for 語句

使用for循環實現上述例子:

awk '
> {
> for( i = 1; i <= $3; i = i+1 ){
> printf("\t%.2f\n", $1*(1+$2)^i)
> }
> }
> '
1000 .06 5
        1060.00
        1123.60
        1191.02
        1262.48
        1338.23
1000 .12 5
        1120.00
        1254.40
        1404.93
        1573.52
        1762.34
複製代碼

數組

awk 爲存儲一組相關的值提供了數組,雖然數組給予了awk很強的能力,可是在這裏咱們僅僅展現一個簡單的例子。 第一個動做將輸入行存爲數組 line 的連續元素; 第一行放在line[1],第二行放在line[2]。 END 動做使用一個while語句從後往前打印數組中的輸入行:

# 反轉-按行逆序打印輸入

{line[NR] = $0}

END {
        i = NR
        while(i > 0){
            print line[i]
            i = i-1
        }
}

複製代碼
awk '
> {line[NR] = $0}
> 
> END {
>         i = NR
>         while(i > 0){
>             print line[i]
>             i = i-1
>         }
> }' emp.data

# 輸出結果爲:
Susie   4.25    18
Mary    5.50    22
Mark    5.00    20
kathy   4.00    10
Dan     3.75    0
Beth    4.00    0
複製代碼

--dump-variables 操做查看全局變量

-dump-variables[=file] 操做能夠打印全局變量到文件中,默認是「awkvars.out」文件。

awk --dump-variables ''

# 查看文件awkvars.out 
cat awkvars.out 

ARGC: number (1)
ARGIND: number (0)
ARGV: array, 1 elements
BINMODE: number (0)
CONVFMT: string ("%.6g")
ERRNO: number (0)
FIELDWIDTHS: string ("")
FILENAME: string ("")
FNR: number (0)
FS: string (" ")
IGNORECASE: number (0)
LINT: number (0)
NF: number (0)
NR: number (0)
OFMT: string ("%.6g")
OFS: string (" ")
ORS: string ("\n")
RLENGTH: number (0)
RS: string ("\n")
RSTART: number (0)
RT: string ("")
SUBSEP: string ("\034")
TEXTDOMAIN: string ("messages")

複製代碼

--help 操做能夠尋得幫助

awk --help
# 輸出信息以下:

Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:          GNU long options:
        -f progfile             --file=progfile
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
        -m[fr] val
        -O                      --optimize
        -W compat               --compat
        -W copyleft             --copyleft
        -W copyright            --copyright
        -W dump-variables[=file]        --dump-variables[=file]
        -W exec=file            --exec=file
        -W gen-po               --gen-po
        -W help                 --help
        -W lint[=fatal]         --lint[=fatal]
        -W lint-old             --lint-old
        -W non-decimal-data     --non-decimal-data
        -W profile[=file]       --profile[=file]
        -W posix                --posix
        -W re-interval          --re-interval
        -W source=program-text  --source=program-text
        -W traditional          --traditional
        -W usage                --usage
        -W use-lc-numeric       --use-lc-numeric
        -W version              --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
        gawk '{ sum += $1 }; END { print sum }' file
        gawk -F: '{ print $1 }' /etc/passwd
複製代碼

--version 查看版本信息

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/.
複製代碼

-v 操做

-v 操做容許給一個變量分配值。容許在程序執行以前分配。

awk -v name=LFF 'BEGIN {printf("username=%s\n", name)}'

# 輸出結果爲:
username=LFF
複製代碼

--lint 操做提示信息

--lint 操做容許輸出檢查信息,好比當參數提供錯誤,會將警告信息看成錯誤。

awk --lint '' /bin/ls

# 輸出結果爲:
awk: warning: empty program text on command line
awk: warning: source file does not end in newline
awk: warning: no program text at all!
複製代碼

正則匹配

匹配輸入行中包含字符a的行,所有輸出。

awk '/a/ {print $0}'  emp.data
 # 輸出結果爲:
Dan     3.75    0
kathy   4.00    10
Mark    5.00    20
Mary    5.50    22
複製代碼

打印輸入行中包含字符a的行數:

awk '/a/ {++cnt} END {print "匹配的行數爲:", cnt}' emp.data
 # 輸出結果爲:
匹配的行數爲: 4
複製代碼

內置變量

ARGC :命令行中提供的參數個數

shell awk 'BEGIN {print "Arguments =", ARGC}' One Two Three Four Arguments = 5

ARGV 表示命令行入參構成的數組,索引是 0~ARGC-1
awk 'BEGIN { 
> for (i = 0; i < ARGC - 1; ++i) { 
> printf "ARGV[%d] = %s\n", i, ARGV[i] 
> } 
> }' one two three four
 # 輸出結果爲:
ARGV[0] = awk
ARGV[1] = one
ARGV[2] = two
ARGV[3] = three
複製代碼
CONVFMT

表示數字的轉換格式。默認值是 %.6g

awk 'BEGIN { print "Conversion Format =", CONVFMT }'

#輸出:
Conversion Format = %.6g
複製代碼
ENVIRON 環境變量
awk 'BEGIN { print ENVIRON["USER"] }'
 # 輸出當前用戶
deploy
複製代碼

咱們能夠藉助env命令查看linux服務器上的所有環境變量:

env
 # 查看當前服務器上的全部環境變量
HOSTNAME=sz-local3
TERM=vt100
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=10.89.4.224 53217 22
QTDIR=/usr/lib64/qt-3.3
OLDPWD=/data/app
QTINC=/usr/lib64/qt-3.3/include
SSH_TTY=/dev/pts/0
GREP_OPTTIONS=--color=always
USER=deploy
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/deploy
PATH=/usr/lib/jdk1.7.0_76/bin:/usr/lib64/qt-3.3/bin:/data/app/node-v4.2.4-linux-x64/bin:/usr/lib/jdk1.7.0_76/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/deploy/bin
PWD=/data/app/lff
JAVA_HOME=/usr/lib/jdk1.7.0_76
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/home/deploy
LOGNAME=deploy
QTLIB=/usr/lib64/qt-3.3/lib
CVS_RSH=ssh
CLASSPATH=/usr/lib/jdk1.7.0_76/lib:/usr/lib/jdk1.7.0_76/lib:
SSH_CONNECTION=10.89.4.224 53217 10.193.1.27 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
_=/bin/env
複製代碼
FILENAME 表示當前文件
awk 'END {print FILENAME}' emp.data
 # 輸出結果爲:
emp.data
複製代碼
FS 表示文件分隔符

FS 表示文件分割符,默認是空白字符。也可使用 -F 命令行變動。

awk 'BEGIN {print "FS = " FS}' | cat -vte
 # 輸出結果爲:
FS =  $
複製代碼
NF 表示當前行的字段(列數)
NR 表示當前讀到的行數
RLENGTH

表示匹配函數 match 到的字符串的長度。

awk '
BEGIN {
       if(match("One Two Three", "re")){
          print RLENGTH
       }
}'
 # 匹配到了Three中的re,輸出結果爲:
2
複製代碼
RSTART 表示第一個match函數匹配到的字符串中的位置
awk ' BEGIN { if(match("One Two Three There", "re")){ print RSTART } }'

# 從O開始,到Three的r,位置處於11,輸出結果爲:
11
複製代碼
$0 表示所有的輸入記錄
$n 表示第n列(第n個字段),以文件分隔符分隔,默認是空白字符。
ARGIND 表示當前處理的 ARGV 的索引值
PROCINFO 表示進程相關信息
awk 'BEGIN {print PROCINFO["pid"]}'
5142
複製代碼

運算符操做

自增符操做
awk 'BEGIN {print ++a}'
# 先自增,輸出結果爲:
1
# 後自增,輸出結果爲:
awk 'BEGIN {print a++}'
0
複製代碼
自減符操做
awk 'BEGIN {print --a}'
-1
awk 'BEGIN {print a--}'
0
複製代碼
+=、 -=、 *=、/=、%=、 ^=、**=操做
awk 'BEGIN {print cnt+=10; print cnt}'
10
10

awk 'BEGIN {cnt=10 ;print cnt*=10; print cnt}'
100
100

awk 'BEGIN {cnt=10 ;print cnt-=10; print cnt}'
0
0
awk 'BEGIN {cnt=10 ;print cnt/=10; print cnt}'
1
1
awk 'BEGIN {cnt=10 ;print cnt%=10; print cnt}'
0
0
awk 'BEGIN {cnt=10 ;print cnt^=10; print cnt}'
10000000000
10000000000
awk 'BEGIN {cnt=10 ;print cnt**=10; print cnt}'
10000000000
10000000000
複製代碼
關係運算符
  • ==
  • !=
  • <
  • <=
  • >
  • >=
邏輯運算符
  • &&
  • ||
  • !
三目運算符
  • ? :
字符串鏈接符

空白字符是字符串鏈接符

awk 'BEGIN {a="hello, "; b="world!"; c= a b; print(c)}'
 # 輸出鏈接結果
hello, world!
複製代碼
數組關係操做符

for in 操做經常使用於遍歷數組。

awk '
> BEGIN { arr[1] = "a"; arr[2] = "b"; arr[3] = "c"; 
> for(i in arr){
> print("a[", i, "]=", arr[i])
> }
> }'
 # 遍歷輸出數組元素:
a[ 1 ]= a
a[ 2 ]= b
a[ 3 ]= c

複製代碼
正則表達式操做符
  • 點符**.** : 匹配任意單個字符

示例:

echo -e "cat\nbat\nfun\nfin\nfan" | awk '/f.n/'

fun
fin
fan
複製代碼
  • **^**符:匹配開頭

匹配 The 開頭的字符串:

echo -e "This\nThat\nThere\nTheir\nthese" | awk '/^The/'

There
Their
複製代碼
  • **$**符:匹配結尾

匹配 n 結尾的字符串:

echo -e "knife\nknow\nfun\nfin\nfan\nnine" | awk '/n$/'

fun
fin
fan
複製代碼
  • [] 符 :匹配字符集多選一

匹配 Call 或者 Tall:

echo -e "Call\nTall\nBall" | awk '/[CT]all/'
 
Call
Tall
複製代碼
  • 排除匹配

使用^排除,匹配不是 Call且不是Tall的字符串:

echo -e "Call\nTall\nBall" | awk '/[^CT]all/'

Ball
複製代碼
  • 可選匹配

匹配 Call 或者 Tall

echo -e "Call\nTall\nBall\nSmall\nShall" | awk '/Call|Ball/'

Call
Ball
複製代碼
  • 符號 :0 或 1次匹配
echo -e "Colour\nColor" | awk '/Colou?r/'

Colour
Color
複製代碼
  • * 符號: 表示0或多個匹配
echo -e "ca\ncat\ncatt" | awk '/cat*/'

ca
cat
catt
複製代碼
  • () 分組匹配
echo -e "Apple Juice\nApple Pie\nApple Tart\nApple Cake" | awk 
   '/Apple (Juice|Cake)/'
   
Apple Juice
Apple Cake
複製代碼

數組

awk 'BEGIN {
   fruits["mango"] = "yellow";
   fruits["orange"] = "orange"
   print fruits["orange"] "\n" fruits["mango"]
}'

orange
yellow
複製代碼
delete 刪除數組元素
awk 'BEGIN {
   fruits["mango"] = "yellow";
   fruits["orange"] = "orange";
   delete fruits["orange"];
   for(i in fruits){print fruits[i]}
}'
 # 刪除orange後,只剩下yello
yellow

複製代碼
多維數組
100   200   300
400   500   600
700   800   900
複製代碼

array[0][0] 存儲 100,array[0][1] 存儲 200。 正確的語法是 array["0,0"] = 100

awk 'BEGIN {
   array["0,0"] = 100;
   array["0,1"] = 200;
   array["0,2"] = 300;
   array["1,0"] = 400;
   array["1,1"] = 500;
   array["1,2"] = 600;

 # print array elements
   print "array[0,0] = " array["0,0"];
   print "array[0,1] = " array["0,1"];
   print "array[0,2] = " array["0,2"];
   print "array[1,0] = " array["1,0"];
   print "array[1,1] = " array["1,1"];
   print "array[1,2] = " array["1,2"];
}'
複製代碼

字符串函數

index(str, substr)

子串 substr 出如今字符串 str 中的開始位置,從1開始計數。

awk 'BEGIN {print index("Hello", "ll")}'
3
複製代碼
gsub(regex, sub, string)

正則匹配 regex,將其替換爲 sub指定的內容, string是所選的字符串。

awk 'BEGIN { str = "Hello,World!"; gsub("World", "Lily", str); print str}'
Hello,Lily!
複製代碼
match(str, regex)

匹配則返回regex在str中的起始位置,不然返回0表示沒有匹配到。

awk 'BEGIN {str = "Hello,world!"; ret = match(str, "wo"); print str, ret}'
Hello,world! 7
複製代碼
split(str, arr, regex)

將 str 按 regex 匹配拆分,獲得的每一個拆分做爲元素保存在 arr 數組中。

awk 'BEGIN {str = "Hello,Hellokitty"; split(str, arr, ",");  
for(ele in arr){
    print arr[ele]
}}'

Hello
Hellokitty
複製代碼
strtonum(str)

將字符串強轉成數值類型, str開頭是0的話會轉爲八進制, 是0x或0X開頭的話會轉爲十六進制。

awk 'BEGIN {
> print "Decimal num = " strtonum("123")
> print "Octal num = " strtonum("0123")
> print "Hexadecimal num = " strtonum("0x123")
> }'
Decimal num = 123
Octal num = 83
Hexadecimal num = 291
複製代碼
substr(str, start, l)

獲取字串,從字符串 str 中的 start位置開始截取長度爲 L 的字符串。

awk 'BEGIN {str = "nihaoya!"; print substr(str, 1, 2)}'
ni
複製代碼
tolower(str)

將字符串 str 小寫化。

awk 'BEGIN{ print tolower("HeLLo")}'
hello
複製代碼
toupper(str)

將字符串 str 大寫化。

awk 'BEGIN{ print toupper("HeLLo")}'
HELLO
複製代碼

時間函數

systime()

獲取自 1970-01-01 00:00:00 至今的unix時間戳

awk 'BEGIN {print systime()}'
1545742584
複製代碼
mktime(datespec)

將指定的日期格式串轉換爲時間戳,datespec 格式是 YYYY mm dd HH MM SS

awk 'BEGIN {print mktime("2018 12 25 21 07 00")}'
1545743220
複製代碼
strftime(format, timestamp)

將時間戳 timestamp 轉換成指定格式format的字符串

awk 'BEGIN {
> print strftime("Time = %m/%d/%Y %H:%M:%S", systime())
> }'
Time = 12/25/2018 21:11:09
複製代碼

位操做函數

and

按位與

awk 'BEGIN {
   num1 = 10
   num2 = 6
   printf "(%d AND %d) = %d\n", num1, num2, and(num1, num2)
}'
 # 輸出結果爲:
(10 AND 6) = 2
複製代碼
lshift(num, size)

將num按位左移size位數, 左移一位至關於乘以2

awk 'BEGIN {print lshift(10, 1)}'
20
複製代碼
rshift(num, size)

將num按位右移size位數, 右移一位至關於除以2

awk 'BEGIN {print rshift(10, 1)}'
5
複製代碼
or 按位或
awk 'BEGIN {
   num1 = 10
   num2 = 6
   printf "(%d OR %d) = %d\n", num1, num2, or(num1, num2)
}'
 # 輸出結果爲:
(10 OR 6) = 14
複製代碼
xor 異或
awk 'BEGIN {
   num1 = 10
   num2 = 6
   printf "(%d XOR %d) = %d\n", num1, num2, xor(num1, num2)
}'
 # 輸出結果爲:
(10 XOR 6) = 12
複製代碼

自定義函數

語法形式:

function function_name(argument1, argument2, ...) { 
   function body
}
複製代碼

示例:

# Returns minimum number
function find_min(num1, num2){
   if (num1 < num2)
   return num1
   return num2
}
# Returns maximum number
function find_max(num1, num2){
   if (num1 > num2)
   return num1
   return num2
}
# Main function
function main(num1, num2){
 # Find minimum number
   result = find_min(10, 20)
   print "Minimum =", result
  
 # Find maximum number
   result = find_max(10, 20)
   print "Maximum =", result
}
# Script execution starts here
BEGIN {
   main(10, 20)
}
複製代碼

輸出轉移操做

重定向數據到文件

咱們還能夠將數據導入到文件中。在 print 或者 printf 後增長重定向的文件語句。 語法:

print data > outputfile

將數據 data 寫入到 outputfile,若是 outputfile 不存在則建立。當指定重定向時,文件 output 會清除全部內容,而後寫入數據。順序寫操做則不會提早清除文件內容,只是追加。

#"Old data" 寫入 message.txt 文件中,沒有則建立 message.txt 文件。
echo "Old data" > message.txt
# 查看文件內容
cat message.txt 
# 輸出結果:
Old data
複製代碼

而後執行:

awk 'BEGIN {print "Hello,World!" > "message.txt"}'
cat message.txt 
# 文件的舊內容清楚了,內容已經被替換
Hello,World!
複製代碼
追加內容到文件中

print DATA >> output-file

echo "Old data" > /tmp/message.txt
cat /tmp/message.txt
# 查看文件內容
Old data
 # 追加內容到文件中
awk 'BEGIN { print "Hello, World !!!" >> "/tmp/message.txt" }'
cat /tmp/message.txt
 # 輸出內容:
Old data
Hello, World !!!
複製代碼
管道 pipe

可能須要發送輸出數據到其它程序,經過管道而不是文件。 這種轉移方式會打開一個管道命令,而且會經過管道將數據項經過管道傳到另外一個進程去執行命令。 轉移參數是一個 awk 表達式。

管道的語法以下:

print items | command

示例:使用 tr 命令將小寫轉換爲大寫

awk 'BEGIN { print "hello, world !!!" | "tr [a-z] [A-Z]" }'
HELLO, WORLD !!!
複製代碼

更過關於 tr 的使用方法,可使用 tr --help 查看幫助信息。

雙向通訊

awk 能夠經過 |& 跟外部進程通訊。

awk 'BEGIN {
> cmd = "tr [a-z] [A-Z]"
> print "hello, world !!!" |& cmd
> close(cmd, "to")
> 
> cmd |& getline out
> print out;
> close(cmd);
> }'
HELLO, WORLD !!!
複製代碼

說明:

  • 第一條語句,cmd="tr [a-z] [A-Z]" ,是咱們創建雙向通訊的命令。
  • 接下來的語句,print 命令提供輸入到 tr 命令。 這裏的 |& 表示雙向通訊。
  • 第三條語句,close(cmd,"to") ,在完成執行後,關閉 to 進程。
  • cmd |& getline out 藉助getline函數將結果輸出 到 out 變量中。
  • 最後打印out,並使用close函數關閉命令。

整齊打印

awk 'BEGIN { printf "Hello\nWorld\n" }'
 # 輸出結果爲:
Hello
World
複製代碼
水平tab間隔打印
awk 'BEGIN { printf "Sr No\tName\tSub\tMarks\n" }'

Sr No   Name    Sub Marks
複製代碼
垂直tab打印
awk 'BEGIN { printf "Sr No\vName\vSub\vMarks\n" }'
 # 輸出結果爲:
Sr No
     Name
         Sub
            Marks

複製代碼
回車打印
awk 'BEGIN { printf "Field 1\rField 2\rField 3\rField 4\n" }'

輸出:
Field 4
複製代碼
換頁打印
awk 'BEGIN { printf "Sr No\fName\fSub\fMarks\n" }'
Sr No
     Name
         Sub
            Marks
複製代碼
格式說明符
  • %c : 表示一個單個字符
awk 'BEGIN { printf "ASCII value 65 = character %c\n", 65 }'
ASCII value 65 = character A
複製代碼
  • %d and %i : 表示十進制的整數
awk 'BEGIN { printf "Percentags = %d\n", 80.66 }'

輸出結果爲:
Percentags = 80
複製代碼
  • %e and %E : 科學記數法
awk 'BEGIN { printf "Percentags = %E\n", 80.66 }'

輸出結果爲:
Percentags = 8.066000e+01
複製代碼
  • %f : 浮點數
awk 'BEGIN { printf "Percentags = %f\n", 80.66 }'

輸出結果爲:
Percentags = 80.660000
複製代碼
  • %s : 表示字符串
awk 'BEGIN { printf "Name = %s\n", "Sherlock Holmes" }'

輸出結果爲:

Name = Sherlock Holmes
複製代碼
  • %nd : 指定寬度打印
awk 'BEGIN { 
   num1 = 10; num2 = 20; printf "Num1 = %10d\nNum2 = %10d\n", num1, num2 
}'
 # 輸出結果爲:
Num1 =         10
Num2 =         20
複製代碼

AWK 概覽

AWK 是一種解釋性編程語言。是專門爲處理文本而設計的。名字是來自於設計者的名字 —— Alfred Aho, Peter Weinberger, and Brian Kernighan.

AWK 的類型

  • AWK : AT&T 實驗室
  • NAWK :AWK 的新的改進版本
  • GAWK : GNU AWK。 全部GNU/Linux發行版都是GAWK。它與AWK和NAWK徹底兼容。

AWK 的典型應用場景

  • 文本處理
  • 生成格式化的文本報告
  • 處理算術操做
  • 處理字符串操做

AWK 環境

描述如何在 GNU/Linux 系統中安裝 AWK 環境。

安裝包管理器

通常狀況下, AWK 默認在大都數 GNU/Linux 系統中都是安裝發行的。 你可使用 which 命令,檢查awk在系統中是否安裝好了。 若是沒有安裝 awk, 能夠按以下命令藉助 高級安裝包 APT安裝 AWK:

sudo apt-get update
sudo apt-get install gawk
複製代碼
yum install gawk
 # 查看
which awk
 # 輸出結果爲:
/bin/awk
複製代碼

從源代碼中安裝:

相關文章
相關標籤/搜索