AWK常见用法

AWK是GUN/Linux下的其中一个文本处理工具,简洁又强大。


程序结构

初始化

1
BEGIN { ??? }

可选,awk程序启动时执行一次。

循环块

1
/pattern/ { ??? }

pattern为正则表达式

END

1
END { ??? }

可选,结束时执行一次。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat >> marks.txt
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
$ awk 'BEGIN{printf "Sr No\tName\tSub\tMarks\n"} {print}' marks.txt
Sr No Name Sub Marks
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89

辅助选项

加载脚本文件

-f ???--file=???

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat >> command.awk
BEGIN {
printf "Sr No\tName\tSub\tMarks\n"
}
{
print
}
$ awk -f command.awk marks.txt
Sr No Name Sub Marks
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89

预先分配变量

-v var=???--assign=var=???

1
2
$ awk -v name=Jerry 'BEGIN{printf "Name = %s\n", name}'
Name = Jerry

预先指定分隔符

-F ???--field-separator=???
指定多个分隔符: -F '[:,./]'


简单实例

打印指定列

打印第3、4列

1
2
3
4
5
6
$ awk '{print $3 "\t" $4}' marks.txt
Physics 80
Maths 90
Biology 87
English 85
History 89

打印模式匹配行

a的所有行,正则表达式语法和bash一样。

1
2
3
4
5
6
7
8
$ awk '/a/ {print $0}' marks.txt
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
# 或
# $ awk '/a/' marks.txt

正则表达式语法:

1
2
3
4
5
6
7
8
9
10
/^abc/ 表示以abc开头,其中^表示在行首位置进行匹配。
/abc$/ 表示以abc结尾,其中$表示在行尾位置进行匹配。
/abc/ 表示当前记录行中出现了abc串。
/[a-d]/ 表示与a-d中的任意一个字符匹配。即当前行中只要有a-d中的任意一个字符就匹配成功。
/[acwy]/ 表示与a、c、w、y中的任意一个字符匹配。即当前行中只要有a、c、w、y中的任意一个字符就匹配成功。
/[^a-d]/ 表示不与a-d中的任意一个字符做匹配。
/cut|pot/ 表示与cut匹配或与pot匹配。
/[ABC]*/ 表示与A、B、C中任意一个出现0次或多次的字符相匹配。
/[ABC]+/ 表示与A、B、C中任意一个出现1次或多次的字符相匹配。
/./ 表示任意一个字符,“.”表示任意一个字符。

打印匹配行指定列

a的所有行里,打印第3,4列。

1
2
3
4
5
$ awk '/a/ {print $3 "\t" $4}' marks.txt
Maths 90
Biology 87
English 85
History 89

打印符合条件行

长度大于18

1
2
3
4
$ awk 'length($0) > 18 {print}' marks.txt
# 或
# $ awk 'length($0) > 18' marks.txt

不止打印

统计含a的行数

1
2
$ awk -v cnt=0 '/a/ { ++cnt } END { print "Count = " cnt}' marks.txt
Count = 4


内置变量

FILENAME

当前文件名

1
2
$ awk 'END {print FILENAME}' marks.txt
marks.txt

BEGIN块未定义

FS OFS

域分隔符:读取输入时分割
输出域分隔符:输出时分割

1
2
$ awk -F; 'END {print "FS = " FS}' marks.txt
FS = ;

RS ORS

行分隔符
输出行分隔符

NF

number of field,当前行总域数

1
2
3
4
5
6
$ awk '{print NF}' marks.txt
4
4
4
4
4

只打印一次:

1
2
$ awk 'END {print NF}' marks.txt
4

NR

number of input records,当前行数

1
2
3
4
5
6
$ awk '{print NR}' marks.txt
1
2
3
4
5

总行数:

1
2
$ awk 'END {print NR}' marks.txt
5


运算

算数运算

1
2
$ awk 'BEGIN { a = 10; b = 20.1; print (a + b) }'
30.1

逻辑运算

1
2
$ awk 'BEGIN { a = 10; b = 20.1; print (a != b)}'
1
1
2
$ awk 'BEGIN { a = 10; b = 20; (a > b) ? max = a : max = b; print "Max =", max}'
Max = 20

字符串拼接

1
2
$ awk 'BEGIN { str1="Hello, "; str2="World"; str3 = str1 str2; print str3 }'
Hello, World

模式匹配符

匹配:

1
2
3
4
5
6
$ awk '$0 ~ 9' marks.txt
2) Rahul Maths 90
5) Hari History 89
# 等价于
# awk '/9/' marks.txt

不匹配:

1
2
3
4
$ awk '$0 !~ 9' marks.txt
1) Amit Physics 80
3) Shyam Biology 87
4) Kedar English 85


控制语句

if-elseif-elsewhilefordo-while等,和C语言类似。
for (i in array)用于遍历数组。


内置函数

length(str)

字符串长度

rand()

返回[0, 1)之间的随机数

1
2
$ awk 'BEGIN { print rand() }'
0.757217

gsub(regex, sub, str=$0)

全局替换

1
2
3
4
5
6
$ awk '{ gsub("a", "A"); print }' marks.txt
1) Amit Physics 80
2) RAhul MAths 90
3) ShyAm Biology 87
4) KedAr English 85
5) HAri History 89

sub(regex, sub, str=$0)

替换

1
2
3
4
5
6
$ awk '{ sub("a", "A"); print }' marks.txt
1) Amit Physics 80
2) RAhul Maths 90
3) ShyAm Biology 87
4) KedAr English 85
5) HAri History 89

index(str, sub)

子串首次匹配位置,从1开始计数,匹配不到返回0。

match(str, regex)

index类似,但是匹配正则表达式。

substr(str, start, length)

按位置和长度截取字符串。