分隔符
-F fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。# 以逗号分割每行,打印第一列,第二列awk -F, '{print $1,$2}' log.txt# 使用内建变量,仍然是以逗号分割,打印第一列,第二列awk 'BEGIN{FS=","} {print $1,$2}' log.txt# 使用多个分隔符.先使用空格分割,然后对分割结果再使用","分割awk -F '[ ,]' '{print $1,$2,$5}' log.txt
赋值变量的方法
-v var=value
赋值一个用户定义变量。
log.txt文本内容如下
2 this is a test3 Are you like awkThis's a test10 There are orange,apple,mongo
$ awk -va=1 '{print $1,$1+a}' log.txt #命令---------------------------------------#输出2 33 4This's 110 11
$ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt #命令---------------------------------------------#输出2 3 2s3 4 3sThis's 1 This'ss10 11 10s
AWK脚本调用
$ awk -f cal.awk log.txt
关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。
- BEGIN{ 这里面放的是**执行前的语句** }
- END {这里面放的是处理完所有的行后要**执行的语句** }
- {这里面放的是处理**每一行时要执行的语句**}
DEMO:
文本:score.txt
$ cat score.txtMarry 2143 78 84 77Jack 2321 66 78 45Tom 2122 48 77 71Mike 2537 87 97 95Bob 2415 40 57 62
脚本:cal.awk
$ cat cal.awk#!/bin/awk -f#运行前BEGIN {math = 0english = 0computer = 0printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"printf "---------------------------------------------\n"}#运行中{math+=$3english+=$4computer+=$5printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5}#运行后END {printf "---------------------------------------------\n"printf " TOTAL:%10d %8d %8d \n", math, english, computerprintf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR}
结果
$ awk -f cal.awk score.txtNAME NO. MATH ENGLISH COMPUTER TOTAL---------------------------------------------Marry 2143 78 84 77 239Jack 2321 66 78 45 189Tom 2122 48 77 71 196Mike 2537 87 97 95 279Bob 2415 40 57 62 159---------------------------------------------TOTAL: 319 393 350AVERAGE: 63.80 78.60 70.00
常见函数
基本函数
参考:https://www.runoob.com/w3cnote/awk-built-in-functions.html
自定义函数
# 返回最小值function find_min(num1, num2){if (num1 < num2)return num1return num2}# 返回最大值function find_max(num1, num2){if (num1 > num2)return num1return num2}# 主函数function main(num1, num2){# 查找最小值result = find_min(10, 20)print "Minimum =", result# 查找最大值result = find_max(10, 20)print "Maximum =", result}# 脚本从这里开始执行BEGIN {main(10, 20)}
$ awk -f functions.awkMinimum = 10Maximum = 20
流程控制
IF
awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d 是偶数\n", num }'
IF-ELSE
awk 'BEGIN {num = 11;if (num % 2 == 0) printf "%d 是偶数\n", num;else printf "%d 是奇数\n", num}'
IF-ELSE-IF
awk 'BEGIN {a=30;if (a==10)print "a = 10";else if (a == 20)print "a = 20";else if (a == 30)print "a = 30";}'
FOR
awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
BREAK
awk 'BEGIN {sum = 0; for (i = 0; i < 20; ++i) {sum += i; if (sum > 50) break; else print "Sum =", sum}}'
Continue
$ awk 'BEGIN {for (i = 1; i <= 20; ++i) {if (i % 2 == 0) print i ; else continue} }'
Exit
awk 'BEGIN {sum = 0; for (i = 0; i < 20; ++i) {sum += i; if (sum > 50) exit(10); else print "Sum =", sum}}'echo $?10
正则匹配
# 输出第二列包含 "th",并打印第二列与第四列$ awk '$2 ~ /th/ {print $2,$4}' log.txt---------------------------------------------this a# 输出包含 "re" 的行$ awk '/re/ ' log.txt---------------------------------------------3 Are you like awk10 There are orange,apple,mongo# 忽略大小写$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt---------------------------------------------2 this is a testThis's a test
#取反$ awk '$2 !~ /th/ {print $2,$4}' log.txt---------------------------------------------Are likeaThere orange,apple,mongo#取反$ awk '!/th/ {print $2,$4}' log.txt---------------------------------------------Are likeaThere orange,apple,mongo
内建变量
FS:Field Separator 分隔符
- FS 可以是任意字符或者正则表达式
- FS 可以多次改变, 不过会保持不变直到被明确修改。不过如果想要改变字段分隔符, 最好是在读入文本之前就改变 FS, 这样改变才会在你读入的文本生效。
OFS: 输出字段分隔符变量
awk -F':' 'BEGIN{OFS="=";} {print $3,$4;}' /etc/passwd
RS:Record Separator 记录分隔符
ORS: 输出记录分隔符变量
$ cat student.txtJones2143788477Gondrol2321565845RinRao2122383765Edwin2537786745Dayan2415304720
# 两个回车作为一个记录的分隔符,单个回车作为记录的内部分隔符$ cat student.awkBEGIN {RS="\n\n";FS="\n";}{print $1,$2;}$ awk -f student.awk student.txtJones 2143Gondrol 2321RinRao 2122Edwin 2537Dayan 2415
NR: 记录数变量
NR(Number of Record) 表示的是已经处理过的总记录数目,或者说行号(不一定是一个文件,可能是多个)。下面的例子,NR 表示行号,在 END 部分,NR 就是文件中的所有记录数目。
NF:一条记录的记录数目
NF(Number for Field)表示的是,一条记录的字段的数目. 它在判断某条记录是否所有字段都存在时非常有用。
cat student-marksJones 2143 78 84 77Gondrol 2321 56 58 45RinRao 2122 38 37Edwin 2537 78 67 45Dayan 2415 30 47
$ awk '{print NR,"->",NF}' student-marks1 -> 52 -> 53 -> 44 -> 55 -> 4
FILENAME: 当前输入文件的名字
FNR: 当前输入文件的记录数目
awk '{print FILENAME, "FNR= ", FNR," NR= ", NR}' student-marks bookdetailsstudent-marks FNR= 1 NR= 1student-marks FNR= 2 NR= 2student-marks FNR= 3 NR= 3student-marks FNR= 4 NR= 4student-marks FNR= 5 NR= 5bookdetails FNR= 1 NR= 6bookdetails FNR= 2 NR= 7bookdetails FNR= 3 NR= 8bookdetails FNR= 4 NR= 9bookdetails FNR= 5 NR= 10
