分隔符
-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 test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
$ awk -va=1 '{print $1,$1+a}' log.txt #命令
---------------------------------------
#输出
2 3
3 4
This's 1
10 11
$ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt #命令
---------------------------------------------
#输出
2 3 2s
3 4 3s
This's 1 This'ss
10 11 10s
AWK脚本调用
$ awk -f cal.awk log.txt
关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。
- BEGIN{ 这里面放的是**执行前的语句** }
- END {这里面放的是处理完所有的行后要**执行的语句** }
- {这里面放的是处理**每一行时要执行的语句**}
DEMO:
文本:score.txt
$ cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
脚本:cal.awk
$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-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, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
结果
$ awk -f cal.awk score.txt
NAME NO. MATH ENGLISH COMPUTER TOTAL
---------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
---------------------------------------------
TOTAL: 319 393 350
AVERAGE: 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 num1
return num2
}
# 返回最大值
function find_max(num1, num2)
{
if (num1 > num2)
return num1
return 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.awk
Minimum = 10
Maximum = 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 awk
10 There are orange,apple,mongo
# 忽略大小写
$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt
---------------------------------------------
2 this is a test
This's a test
#取反
$ awk '$2 !~ /th/ {print $2,$4}' log.txt
---------------------------------------------
Are like
a
There orange,apple,mongo
#取反
$ awk '!/th/ {print $2,$4}' log.txt
---------------------------------------------
Are like
a
There 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.txt
Jones
2143
78
84
77
Gondrol
2321
56
58
45
RinRao
2122
38
37
65
Edwin
2537
78
67
45
Dayan
2415
30
47
20
# 两个回车作为一个记录的分隔符,单个回车作为记录的内部分隔符
$ cat student.awk
BEGIN {
RS="\n\n";
FS="\n";
}
{
print $1,$2;
}
$ awk -f student.awk student.txt
Jones 2143
Gondrol 2321
RinRao 2122
Edwin 2537
Dayan 2415
NR: 记录数变量
NR(Number of Record) 表示的是已经处理过的总记录数目,或者说行号(不一定是一个文件,可能是多个)。下面的例子,NR 表示行号,在 END 部分,NR 就是文件中的所有记录数目。
NF:一条记录的记录数目
NF(Number for Field)表示的是,一条记录的字段的数目. 它在判断某条记录是否所有字段都存在时非常有用。
cat student-marks
Jones 2143 78 84 77
Gondrol 2321 56 58 45
RinRao 2122 38 37
Edwin 2537 78 67 45
Dayan 2415 30 47
$ awk '{print NR,"->",NF}' student-marks
1 -> 5
2 -> 5
3 -> 4
4 -> 5
5 -> 4
FILENAME: 当前输入文件的名字
FNR: 当前输入文件的记录数目
awk '{print FILENAME, "FNR= ", FNR," NR= ", NR}' student-marks bookdetails
student-marks FNR= 1 NR= 1
student-marks FNR= 2 NR= 2
student-marks FNR= 3 NR= 3
student-marks FNR= 4 NR= 4
student-marks FNR= 5 NR= 5
bookdetails FNR= 1 NR= 6
bookdetails FNR= 2 NR= 7
bookdetails FNR= 3 NR= 8
bookdetails FNR= 4 NR= 9
bookdetails FNR= 5 NR= 10