目錄
序:回顧shell三劍客的關係
一、awk基礎
1.1awk簡介
1.2基本語法
二 awk中OPTIONS的說明
2.0 參數列表
2.1 -f program-file
2.2 -F fs
2.3 -v var =val
2.4 -d [file]
2.5 -h
2.6 -P 待補充
2.7 -S 待補充
2.8 -V 顯示版本
三 awk中PROGRAM的說明
3.1 通俗理解
3.2 PROGRAM的語法格式
3.3 PROGRAM中兩部分的關係
3.4 awk中對每一行執行PROGRAM的流程
3.5 詳解PROGRAM中PATTERN部分
序:回顧shell三劍客的關係
shell三劍客最擅長解決的問題
sed 解決文件修改的問題
grep 解決查找的問題
awk 解決截取的問題
一、awk基礎
1.1awk簡介
1.1.1awk歷史簡介
a.現在用的是1985年的版本
b. 分支版本
nawk:八十年代的更新
mawk、gawk:GNU項目的
1.1.2awk簡單說明
a.專門爲文本處理而設計的編程語言
b.用於數據提取和報告(生成格式報告)的工具
c.是數據流驅動的腳本語言
包含一組針對文本數據流的操作,可以直接對文本文件進行處理。
可以從管道符獲得數據。
d.擅長處理數據庫和表型文件
e.awk是一種解釋性語言
f.類似於C語言的語法
g.能用很短的程序對文檔資料進行修改、比較、提取、打印輸出
h.本博以awk的gawk爲例,默認情況下centos使用的就是gawk
[root@localhost ~]# ll /usr/bin/awk
lrwxrwxrwx. 1 root root 4 Jan 2 17:02 /usr/bin/awk -> gawk
1.1.3awk的特性和優勢
a.有許多內置函數與內置變量。
b.默認使用的擴展正則表達式。
對比:sed -r,grep -E 使用擴展正則表達式,而sed和grep工具默認使用的是基本正則表達式
k.awk與sed類似,從輸入流裏面一行一行讀取內容,並通過某種規則提取出行後規範化輸出。所以涉及到了記錄分隔符的概念(也就是如果去定義一行應包含哪些內容)。
1.2基本語法
1.2.1 awk程序自動會完成的工作
讀取輸入行
切分字段(使用字段分隔符)
存儲管理
初始化
若使用了用戶自定義變量不需要聲明變量類型,awk內置字符串類型和數值類型變量。
類比數據庫裏面的概念,讀取的每一行我們稱爲記錄,而記錄中以分隔符分隔的爲字段。
1.2.2 語法格式
awk [OPTIONS] -f PROGRAM_FILE [--] filename_list
awk [OPTIONS] [--] PROGRAM filename_list
1.2.3 簡單理解PROGRAM
可以將PROGRAM理解成sed中的script,PROGRAM由多個PATTERN和ACTION組成,PATTERN即爲以某種形式(如正則表達式)去判斷目前該行是否是我所需要處理的行的匹配規則,而ACTION則是匹配成功後需要執行的動作。
#PROGRAM的常用通用格式:
awk [OPTIONS] [--] 'pattern{action};pattern{action};' filename_list
1.2.4 簡單理解字段分隔符
awk搜索文件並把每一個輸入行按照awk原定義好的字段分隔符FS將記錄切分成字段(field)。其中字段分隔符則是每一個awk程序的內置變量之一。當然,awk程序還內置了其他字符串和數值類型的內置變量,用於便捷地表示某些特定的量(例如字段分隔符、記錄分隔符等)。
#例如處理/etc/passwd文件通常會這麼處理
[root@localhost ~]# awk -F: '{print $1,$4}' /etc/passwd
root 0
bin 1
daemon 2
adm 4
lp 7
sync 0
shutdown 0
另外,awk還支持用戶自定義變量而不需要聲明變量的數據類型(因爲awk程序內置了字符串和數值類型)。
#通常使用參數-v var=val的形式指定
1.2.5 簡單理解字段變量
例如:$3是位置參數,代表第三個字段
[tyson@localhost learnawk]$ awk '$3 > 0 { print $1,$2 * $3 }' firstprogram.txt
Kathy 40
Mark 100
Mary 121
Susie 76.5
[tyson@localhost learnawk]$ cat firstprogram.txt
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中的命令部分(PROGRAM部分)用單引號包圍,否則是用shell程序來解析。
用引號包圍命令部分是爲了告訴系統讓awk程序來解析該命令,單引號中包圍的內容是一個完整的awk程序。
1.2.6 簡單理解filname_list含義
可以是多個文件
[tyson@localhost learnawk]$ awk ' $3>0 {print$1,$2 * $3}' firstprogram.txt firstprogram2.txt
Kathy 40
Mark 100
Mary 121
Susie 76.5
Kathy 40
Mark 100
Mary 121
Susie 76.5
1.2.7 第一個awk程序
[tyson@localhost testawk]$ cat text.txt
SR 8649 275 Asia
Canada 3852 25 North_America
China 3705 1032 Asia
USA 3615 237 North_America
Brazil 3286 134 South_America
India 1267 746 Asia
Mexico 762 78 North_America
France 211 55 Europe
Japan 144 120 Asia
Germany 96 61 Europe
England 94 56 Europe
[tyson@localhost testawk]$ awk '$2>3000{ print $2*$3 }' text.txt
2378475
96300
3823560
856755
440324
該awk命令中的program部分(被單引號括起來的部分)是僅有一個pattern{action}對組成的完整程序。
其中:
PATTERN是$2>3000,模式匹配後執行ACTION
ACTION是print $2*$3,打印第二和第三個字段的乘積
二 awk中OPTIONS的說明
2.0 參數列表
常用部分
-f program_file_list
指定包含了awk命令的文件,通常以.awk後綴命名,可以指定多個
-F fs
自定義字段分隔符,用於將每一條記錄分割成字段(field)。默認是空格
-v var=val
在awk程序運行之前爲自定義的變量賦值。該值可以用到BEGIN塊的的ACTION部分中。
-d[file]
將一些awk程序內置變量的最終值排序成列表並打印到文件中(默認在同目錄下生成awkvars.out文件,當然也可以直接指定)
-h
--help
獲取幫助
-P
待補充
-S
待補充
-V
顯示版本
2.1 -f program-file
指定包含了awk命令的文件,不是從命令行參數中去讀取。可以通過-f選項指定多個包含awk命令文件。
[tyson@Tyson Lee testawk]$ awk -f fortext.awk text.txt
Country Aera 0 CONTENT
SR 8649 275 Asia
Canada 3852 25 North_America
China 3705 1032 Asia
USA 3615 237 North_America
Brazil 3286 134 South_America
India 1267 746 Asia
Mexico 762 78 North_America
France 211 55 Europe
Japan 144 120 Asia
Germany 96 61 Europe
England 94 56 Europe
we are donw
[tyson@Tyson Lee testawk]$ cat fortext.awk
BEGIN{
FS=" "
printf("%10s %6s %5d %s\n\n","Country","Aera","POP","CONTENT")
}
{
printf("%10s %6d %5d %s\n",$1,$2,$3,$4)
}
END{
printf("\nwe are donw\n")
}
2.2 -F fs
-F選項可以自定義字段分隔符,既我們可以改變FS變量對應的值來滿足需求。
fs是一個字符串或正則表達式。
例如:使用awk程序對passwd文件進行處理。注意在awk程序中使用變量(內置變量、自定義變量)是不需要用符號“$”引用的,而使用字段變量是需要用符號"$"引用的,這個在接下來的變量部分會提到。
[tyson@Tyson Lee testawk]$ awk -F: '{print $1,$3*$4}' /etc/passwd |grep tyson
tyson 1002001
tyson1 1006009
[tyson@Tyson Lee testawk]$ cat /etc/passwd
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
…………………………………………………………………………………………………………
默認情況下awk中FS的值是空格,OFMT的含義是數值輸出格式。
#後面打印了另一內置變量用以標明FS有輸出空格而不是輸出空內容
[tyson@Tyson Lee testawk]$ awk 'BEGIN{print FS,OFMT}'
%.6g
2.3 -v var =val
程序開始之前將val這個值賦給var這個變量,通過-v指定的變量可以用於awk程序的BEGIN塊中
簡略地說就是賦值一個用戶自定義變量。
[tyson@Tyson Lee testawk]$ awk -v testVar=$USER 'BEGIN{print testVar}'
tyson
2.4 -d [file]
--dump-variables
將一些awk程序內置變量的最終值排序成列表並打印到文件中(默認在同目錄下生成awkvars.out文件,當然也可以直接指定)
[tyson@localhost testawk]$ ll
total 8
-rw-rw-r--. 1 tyson tyson 103 Jan 10 20:36 big
-rw-rw-r--. 1 tyson tyson 304 Jan 10 19:51 text.txt
[tyson@localhost testawk]$ awk -d '$2>3000{ print $2*$3 }' text.txt
2378475
96300
3823560
856755
440324
[tyson@localhost testawk]$ ll
total 12
-rw-rw-r--. 1 tyson tyson 298 Jan 12 14:55 awkvars.out
-rw-rw-r--. 1 tyson tyson 103 Jan 10 20:36 big
-rw-rw-r--. 1 tyson tyson 304 Jan 10 19:51 text.txt
[tyson@localhost testawk]$ cat awkvars.out
ARGC: 2
ARGIND: 1
ARGV: array, 2 elements
BINMODE: 0
CONVFMT: "%.6g"
ERRNO: ""
FIELDWIDTHS: ""
FILENAME: "text.txt"
FNR: 11
FPAT: "[^[:space:]]+"
FS: " "
IGNORECASE: 0
LINT: 0
NF: 4
NR: 11
OFMT: "%.6g"
OFS: " "
ORS: "\n"
RLENGTH: 0
RS: "\n"
RSTART: 0
RT: "\n"
SUBSEP: "\034"
TEXTDOMAIN: "messages"
2.5 -h
--help
獲取awk程序選項說明
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version
2.6 -P 待補充
2.7 -S 待補充
2.8 -V 顯示版本
[tyson@Tyson Lee testawk]$ awk -V
GNU Awk 4.0.2
三 awk中PROGRAM的說明
3.1 通俗理解
awk -d '$2>3000{ print $2*$3 }' text.txt
這個例子中,引號內的就是PROGRAM部分,也就是awk命令的程序部分。
可以將PROGRAM理解成sed中的script,PROGRAM由多個PATTERN和ACTION組成,PATTERN即爲以某種形式(如正則表達式)去判斷目前該行是否是我所需要處理的行的匹配規則,而ACTION則是匹配成功後需要執行的動作。
3.2 PROGRAM的語法格式
每一個PROGRAM部分都是由一個或多個PATTER-ACTION(模式-動作)組成的序列。而不同的調用方式有不同的寫法規範。
#1.PROGRAM寫在一行
awk 'pattern{action};pattern{action};pattern{action}…………' test.txt
#2.PROGRAM寫在文件內
#/test/program.awk
patter { action }
patter { action }
………………
patter { action }
patter { action }
#若PROGRAM寫在文件內則awk命令需要通過這種形式指定包含awk命令的文件
awk -f program.awk test.txt
3.3 PROGRAM中兩部分的關係
parogram中pattern部分和action部分可以只存在其一
action部分省略,默認只將每一行print。
pattern部分被省略,代表着每一行都匹配成功,都會執行後面的action(s)。
3.4 awk中對每一行執行PROGRAM的流程
讀取一行,對該行執行pattern-action(也就是PROGRAM部分)。
對讀取的行進行掃描搜索,搜索行中是否有內容被pattern匹配。
如果行含有被pattern命中的部分則該行標記爲匹配成功。
該行匹配成功:執行action部分。(若未指定動作會有自動輸出)
若匹配不成功:則不執行action部分也不執行自動輸出。
讀取下一行。
3.5 詳解PROGRAM中PATTERN部分
3.5.1 pattern的作用說明
awk程序的pattern與sed的尋址同理,既判斷目前讀取的該行是否是我們所指定的匹配方式所能匹配成功的一行。也就是說只有與所指定的pattern成功匹配纔會對該行執行後面的action,若省略patter則是對每一行都執行action。
3.5.2 與sed尋址的比較
awk的pattern支持的規則:正則表達式、字符串與數值的比較、流程控制語句。
相較而言,sed中script的尋址部分只支持正則表達式。
3.5.3 模式表示方式彙總
常用
BEGIN
END
普通表達式
/regular expression/
正則表達式
進階
關係表達式
模式與
模式或
選擇表達式
pattern1?pattern2:pattern3
模式分組
(pattern)
模式取反
!pattern
模式範圍
pattern1,pattern2
較少使用
BEGINFILE
ENDFILE
3.5.3.4 模式之BEGIN與END
BEGIN :在awk讀取第一個文件第一行前要執行的awk程序(處理輸入流之前)。
END:在awk處理完最後一個文件最後一行後要執行的awk程序(處理完成輸入流全部內容之後)。
3.5.3.4.1 說明
a.他們不匹配任何輸入行
控制初始化和掃尾,不可以與其他模式表達式進行組合
不能缺失action部分。
b.若有多個BEGIN或END這種PATTERN,則按順序執行,不是並行。
c.通常將BEGIN放在PROGRAM部分的開頭,END放在PROGRAM部分的結尾。
3.5.3.4.2 常見作用
BEGIN常用來更改字段分隔符FS。
END用來輸出一些彙總信息。
3.5.3.4.3 案例
首先需要注意幾點:
awk中的action部分使用的是類c語言的語法,而不是shell語法。
不需要初始化變量。
父shell的環境變量不會應用到awk程序。但是沒有在引號內使用變量則這個環境變量仍能夠被識別出來。
在PROGRAM中使用內置變量與用戶自定義變量都不需要使用符號“$”
[tyson@Tyson Lee testawk]$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/tyson/.local/bin:/home/tyson/bin
[tyson@Tyson Lee testawk]$ echo $USER
tyson
[tyson@Tyson Lee testawk]$ awk 'BEGIN{print $USER}'
[tyson@Tyson Lee testawk]$ awk -v USER=$USER 'BEGIN{print USER}'
tyson
實戰案例
[tyson@Tyson Lee testawk]$ cat fortext.awk
BEGIN{
FS=" "
printf("%10s %6s %5d %s\n\n","Country","Aera","POP","CONTENT")
}
{
printf("%10s %6d %5d %s\n",$1,$2,$3,$4)
}
END{
printf("\nwe are donw\n")
}
[tyson@Tyson Lee testawk]$ cat text.txt
SR 8649 275 Asia
Canada 3852 25 North_America
China 3705 1032 Asia
USA 3615 237 North_America
Brazil 3286 134 South_America
India 1267 746 Asia
Mexico 762 78 North_America
France 211 55 Europe
Japan 144 120 Asia
Germany 96 61 Europe
England 94 56 Europe
[tyson@Tyson Lee testawk]$ awk -f fortext.awk text.txt
Country Aera 0 CONTENT
SR 8649 275 Asia
Canada 3852 25 North_America
China 3705 1032 Asia
USA 3615 237 North_America
Brazil 3286 134 South_America
India 1267 746 Asia
Mexico 762 78 North_America
France 211 55 Europe
Japan 144 120 Asia
Germany 96 61 Europe
England 94 56 Europe
we are donw
3.5.3.5 模式之普通表達式
在模式中,可以通過普通表達式的真與假作爲PATTERN來判斷該行是否匹配,如:$1>$2{print $3}。但是在awk程序中,用於進行普通表達式運算的不僅僅可以是數值,還可以是字符串常量、空字符串、子字符串。
並且,awk中PATTERN的普通表達式還可以比較字符串和數值(會進行強制類型轉換)。
最終若結果爲0則該行不匹配,若結果爲非0則該行匹配。
3.5.3.5.1 比較運算符彙總
<
<=
==
等於
!=
不等於
>=
>
~
匹配
!~
不匹配
需要注意的是:
在普通表達式中:~、!~,分別是匹配和不匹配。
在正則表達式中:波浪號不代表上述兩個含義。
3.5.3.5.2 表達式運算彙總
操作
運算符
例子
例子的值
賦值
= += -= *= /= %= ^=
條件表達式
?:
x?y;z
x爲真則表達式值爲y,反之爲z
邏輯或、邏輯與
||、&&
數組成員
in
i in a
若a[i]存在,則爲表達式真
匹配
~ !~
$1~/x/
若第一個字段包含字符x則表達式爲真
關係運算
<=、==、>=、!=、>=、>
拼接
"a""bc"
"abc"
加減乘除和模運算
單目加、單目減
+ -
-x、+x
指數運算
^
自增、自減
++、--
字段
$
$i+1
1+第i個字段的值
組合
()
($i)++
給第i個字段的值加1
需要具備的基礎知識(科班出身應該都懂):
表達式是一種用語判斷的語句,那麼必然可以用於PATTERN中來判斷該行是否匹配。除此之外,ACTION部分當然也可以使用普通表達式,例如{if($1>$2) print $3}。
運算符的優先級問題。
運算符的左右結合問題。
數值比較:比較大小;字符串比較:按照ASCII碼大小逐位比較。
操作數的分類問題:awk中的操作數分常量:字符串與數值;變量:用戶定義的、內建的、或字段的。
3.5.3.6 模式之正則表達式
3.5.3.6.1/regexpr/
當前行能匹配regexpr
3.5.3.6.2expression ~ /regexpr/
expression字符串值包含一段子字符串能夠被regexpr匹配的子字符時,該模式匹配。(expression可以是變量常量表達式等)。
[tyson@Tyson Lee testawk]$ awk '$1~/an/' text.txt
Canada 3852 25 North_America
France 211 55 Europe
Japan 144 120 Asia
Germany 96 61 Europe
England 94 56 Europe
[tyson@Tyson Lee testawk]$ cat text.txt
SR 8649 275 Asia
Canada 3852 25 North_America
China 3705 1032 Asia
USA 3615 237 North_America
Brazil 3286 134 South_America
India 1267 746 Asia
Mexico 762 78 North_America
France 211 55 Europe
Japan 144 120 Asia
Germany 96 61 Europe
England 94 56 Europe
3.5.3.6.3 expression!~/regexpr/
expression字符串值不包含一段子字符串能夠被regexpr匹配的子字符時,該模式匹配。
例如:
awk '$1 ~ /U/{print $0}' file
awk '$1 !~ /U/{print $0}' file
在兩種形式中,正則表達式匹配的不是整行,而是前面表達式所指定的內容,在這裏個例子就是字段1。
[tyson@Tyson Lee testawk]$ awk '$1!~/an/' text.txt
SR 8649 275 Asia
China 3705 1032 Asia
USA 3615 237 North_America
Brazil 3286 134 South_America
India 1267 746 Asia
Mexico 762 78 North_America
3.5.3.7 模式之複合模式
所謂複合模式,就是通過邏輯運算符&&、||、非組合了多個模式的模式。
pattern || pattern
pattern && pattern
#找出前兩個字段同時爲字母或後兩個字段同時爲數字的記錄
[tyson@Tyson Lee testawk]$ awk '$1~/[a-zA-Z]/&&$2~/[a-zA-Z]/||$3~/[0-9]/&&$4~/[0-9]/' testFuhe.txt
a 2 3 4
a b 1 2
a b c d