awk
文本處理,每次讀取一行,并進(jìn)行分片(默認(rèn)用空格分割),然后依次放入變量 $1, $2, $3, ..., $NF 中,其中 $0 用于表示所有分割元素,action 可以對(duì)數(shù)據(jù)進(jìn)行處理。
# program
[pattern] { action }
# 這里的 pattern 可以省略,也可以是正則,也可以是以下將要講到的 BEGIN, END 等。
# action 也可以被省略,默認(rèn)打印所有元素,但是不能都省略 pattern 和 action
$ awk '/regexr/' input_file # 省略了 action,其等價(jià)于 awk '/regexr/{print $0}' input_file
$ awk '{print $1}' input_file # 省略了pattern
# mail_list 用于 awk 分析使用
Amelia 555-5553 amelia.zodiacusque@gmail.com F
Anthony 555-3412 anthony.asserturo@hotmail.com A
Becky 555-7685 becky.algebrarum@gmail.com A
Bill 555-1675 bill.drowning@hotmail.com A
Broderick 555-0542 broderick.aliquotiens@yahoo.com R
Camilla 555-2912 camilla.infusarum@skynet.be R
Fabius 555-1234 fabius.undevicesimus@ucb.edu F
Julie 555-6699 julie.perscrutabor@skeeve.com F
Martin 555-6480 martin.codicibus@hotmail.com A
Samuel 555-3430 samuel.lanceolis@shu.edu A
Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
# inventory-shipped
Jan 13 25 15 115
Feb 15 32 24 226
Mar 15 24 34 228
Apr 31 52 63 420
May 16 34 29 208
Jun 31 42 75 492
Jul 24 34 67 436
Aug 15 34 47 316
Sep 13 55 37 277
Oct 29 54 68 525
Nov 20 87 82 577
Dec 17 35 61 401
Jan 21 36 64 620
Feb 26 58 80 652
Mar 24 75 70 495
Apr 21 70 74 514
執(zhí)行方式
awk [options] -f progfile [--] file …
awk [options] [--] 'program' file …
# -- 表示參數(shù) options 的結(jié)束
# eg
$ awk '{print $1}' mail_list
Amelia
Anthony
Becky
...
# 將處理代碼寫入 program_file 中,用 -f 方式加載
awk -f program_file input_file1 input_file2 ...
還可以寫成腳本方式
#!/bin/awk -f
BEGIN { action } # 文本開始時(shí)執(zhí)行一次
pattern { action } # 文本處理主要在這里
END { action } # 結(jié)束時(shí)執(zhí)行一次
先來進(jìn)行一些簡(jiǎn)單的應(yīng)用
$ awk '/li/ { print $0 }' mail-list
-| Amelia 555-5553 amelia.zodiacusque@gmail.com F
-| Broderick 555-0542 broderick.aliquotiens@yahoo.com R
-| Julie 555-6699 julie.perscrutabor@skeeve.com F
-| Samuel 555-3430 samuel.lanceolis@shu.edu A
$ awk 'NF > 0' mail_list
# NF 可以理解為分割元素?cái)?shù)量
$ awk 'BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }'
# 隨機(jī) 0-100 的 7 個(gè)數(shù)
$ ls -l | awk '{ x += $5 } END{ print "total bytes:" x }'
# 統(tǒng)計(jì)當(dāng)前目錄文件總大小
$ awk -F: '{ print $1 }' /etc/passwd | sort
# -F 指定分割符
$ awk 'END { print NR }' mail_list
# NR 行數(shù),每讀入一行都會(huì)遞增的,結(jié)束時(shí)就是整個(gè)文本的函數(shù)了
$ awk 'NR % 2 == 0' mail_list
# 打印所有偶數(shù)行
包含其它文件 @
## test1 ##
BEGIN {print test1 }
## ##
@include "test2"
BEGIN {print "test2"}
正則表達(dá)比較 ~ 和 !~
exp ~ /regexp/ # 表示 exp 和 regexp 匹配的話返回真
exp !~ /regxep/ # 表示 exp 和 regexp 不匹配時(shí)返回假
$ awk '$1 ~ /J/' inventory-shipped
-| Jan 13 25 15 115
-| Jun 31 42 75 492
-| Jul 24 34 67 436
-| Jan 21 36 64 620
$ awk '$1 !~ /J/' inventory-shipped
-| Feb 15 32 24 226
-| Mar 15 24 34 228
-| Apr 31 52 63 420
-| May 16 34 29 208
…
以上倆等價(jià)于
awk '{ if ($1 ~ /J/) print $0 }' inventory-shipped
awk '{ if ($1 !~ /J/) print $0 }' inventory-shipped
忽略大小寫
x = "aB"
if (x ~ /ab/) … # this test will fail
IGNORECASE = 1
if (x ~ /ab/) … # now it will succeed
Record Splitting
RS 默認(rèn)是換行,通過設(shè)置該值可以改變行輸入的結(jié)尾
$ awk 'BEGIN { RS = "u" } { print $0 }' mail-list
-| Amelia 555-5553 amelia.zodiac
-| sq
-| e@gmail.com F
-| Anthony 555-3412 anthony.assert
-| ro@hotmail.com A
-| Becky 555-7685 becky.algebrar
-| m@gmail.com A
-| Bill 555-1675 bill.drowning@hotmail.com A
-| Broderick 555-0542 broderick.aliq
...
# RS 可以設(shè)置為正則表達(dá)
# RT 為 RS 每次匹配到的內(nèi)容
$ echo record 1 AAAA record 2 BBBB record 3 |
> gawk 'BEGIN { RS = "\n|( *[[:upper:]]+ *)" }
> { print "Record =", $0,"and RT = [" RT "]" }'
-| Record = record 1 and RT = [ AAAA ]
-| Record = record 2 and RT = [ BBBB ]
-| Record = record 3 and RT = [
-| ]
# 類似的還有 FS, 域分割符,默認(rèn)是空格,也可以使用正則
$ echo "John Q. Smith, 29 Oak St., Walamazoo, MI 42139" | awk 'BEGIN {FS=","};{print $2}'
-| 29 Oak St.
使用外部命令,這里使用 date 作為示范,現(xiàn)在有一個(gè)文件的格式如下:
time.txt
1,2017-10-18 03:44:59,2017-10-18 03:46:05
2,2017-10-18 03:48:28,2017-10-18 03:48:47
3,2017-10-18 03:49:23,2017-10-18 03:56:24
4,2017-10-18 03:55:16,2017-10-18 03:56:56
5,2017-10-18 03:58:08,2017-10-18 03:59:16
6,2017-10-18 03:58:32,2017-10-18 03:59:00
7,2017-10-18 03:59:55,2017-10-18 04:01:13
現(xiàn)在計(jì)算兩個(gè)時(shí)間的差,可以寫成以下的格式:
gawk -F ',' '{
cmd_f="date +%s -d \""$2"\"";
cmd_t="date +%s -d \""$3"\"";
cmd_f|getline a; cmd_t|getline b;
print b - a;
}' ./temp_time