目录
序
一、awk的program中print的用法
1.1print函数语法
1.2打印输出每一行
1.3 选择输出
1.4 为记录加上行号
1.5 用更美观的分隔符输出文件信息
二、awk的program中printf的用法
2.1 函数语法
2.2 输出重定向之输出到文件
2.3 输出重定向之输出到管道
由上文可知,awk的基本语法是:
awk [OPTIONS] 'pattern{action};pattern{action};' filename_list 或
awk [OPTIONS] -f program_file filename_list
量和内置变量这两种变量,并且支持用户自定义变量。因此通过print和printf两种输出函数与awk特有的变量结合有诸多玩法。
print expression1,expression2,...,expressionn
print (expression1,expression2,...,expressionn)
print的作用可以简述为,使用awk程序用默认的输出字段分隔符(内置变量OFS)将该函数中用逗号隔开的各表达式的字符串值分隔开并输出。
当pattern省略,每一行都会执行action。print等价于print $0。
[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 '{print}' 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
在print语句中用逗号分隔字段变量,而awk程序默认用空格作为输入数据每条记录的字段的分隔符,而换行符则为分割记录的记录分隔符。
输出数据的字段分隔符和记录分隔符都是可以自定义的,在后续讲解awk的变量的时候会详细提到。而这也正是awk擅长处理表型或数据库型文件的原因。
$number中,number可以是具的值,也可以是表达式,也可以用内置变量如$NF(当前读取到的行的字段数量)。
[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 '{print "total:"NF,$2,$(NF)}' text.txt
total:4 8649 Asia
total:4 3852 North_America
total:4 3705 Asia
total:4 3615 North_America
total:4 3286 South_America
total:4 1267 Asia
total:4 762 North_America
total:4 211 Europe
total:4 144 Asia
total:4 96 Europe
total:4 94 Europe
内置变量NR表示到目前为止,读取到的行的数量,类似于sed的行号计数器。可以用来在行首加行号。字段变量$0表示当前读取到的记录的所有内容。
[tyson@Tyson Lee testawk]$ awk '{print NR,$0}' text.txt
1 SR 8649 275 Asia
2 Canada 3852 25 North_America
3 China 3705 1032 Asia
4 USA 3615 237 North_America
5 Brazil 3286 134 South_America
6 India 1267 746 Asia
7 Mexico 762 78 North_America
8 France 211 55 Europe
9 Japan 144 120 Asia
10 Germany 96 61 Europe
11 England 94 56 Europe
更改ORS(输出的记录分隔符)
例如:将原来的空一行输出改为空两行输出。
[tyson@Tyson Lee testawk]$ awk -F: 'BEGIN{ORS="\n\n"};/tyson/{ print ("username:"$1,"protocol:"$4)}' /etc/passwd
username:tyson protocol:1001
username:tyson1 protocol:1003
[tyson@Tyson Lee testawk]$
更改OFS(输出的字段分隔符)
[tyson@Tyson Lee testawk]$ awk -F: 'BEGIN{OFS="-"};/tyson/{ print ("username:"$1,"protocol:"$4)}' /etc/passwd
username:tyson-protocol:1001
username:tyson1-protocol:1003
需要注意的点:
在这里使用$0是不科学的,因为这样被记录整体作为一个字段输出,就没有讨论分隔的必要。
printf format,expression1,expression2,expressionn
printf (format,expression1,expression2,expressionn)
format是必须的,是一个变量,其字符串值包含字面文本(直接输出)和格式说明符。
字面字符:字面意义的字符,例如“the total is”
格式说明符:百分号、对齐方式、字符串最大宽度格式控制字符、占用字符宽度,如“%-5c”
格式控制符 |
|
c |
ASCII字符 |
d |
十进制 |
e |
科学计数法 |
f |
浮点数 |
s |
字符串 |
% |
打印百分号 |
非常用格式控制符 |
|
g |
|
o |
无符号八进制数 |
x |
无符号十六进制数 |
对齐方式:
连字符-表示左对齐,默认是右对齐。
字符串最大宽度:
用数值指定。需要注意的是这里指定的是能进行格式化输出的最大字符宽度,所以若需要输出的字符串宽度大于该值也不会截断,只是所指定的格式化输出的参数会失效。
默认情况下,awk会将规范化处理后的文本打印到屏幕,而我们可以通过>,>>把输出重定向到文件。
实例1:将不同范围的数据存入多个文件
[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 '{print $1,$3>>($3>1000?"big.txt":"small.txt")}' text.txt
[tyson@Tyson Lee testawk]$ cat big.txt
China 1032
[tyson@Tyson Lee testawk]$ cat small.txt
SR 275
Canada 25
USA 237
Brazil 134
India 746
Mexico 78
France 55
Japan 120
Germany 61
England 56
在标准输出重定向符号的右侧,是否使用双引号有不同的效果。
若是变量不要用双引号,此时重定向会产生多个文件
若是常量则用双引号,此时重定向只会产生单个文件。
实例2:使用某个字段作为名称为每条记录建立一个文件存储
[tyson@Tyson Lee testawk]$ awk '{print $1,$2>$1}' text.txt
[tyson@Tyson Lee testawk]$ ll
total 76
-rw-rw-r--. 1 tyson tyson 12 Jan 13 11:44 Brazil
-rw-rw-r--. 1 tyson tyson 12 Jan 13 11:44 Canada
-rw-rw-r--. 1 tyson tyson 11 Jan 13 11:44 China
-rw-rw-r--. 1 tyson tyson 11 Jan 13 11:44 England
-rw-rw-r--. 1 tyson tyson 11 Jan 13 11:44 France
-rw-rw-r--. 1 tyson tyson 11 Jan 13 11:44 Germany
-rw-rw-r--. 1 tyson tyson 11 Jan 13 11:44 India
-rw-rw-r--. 1 tyson tyson 10 Jan 13 11:44 Japan
-rw-rw-r--. 1 tyson tyson 11 Jan 13 11:44 Mexico
-rw-rw-r--. 1 tyson tyson 8 Jan 13 11:44 SR
-rw-rw-r--. 1 tyson tyson 9 Jan 13 11:44 USA
若用括号把重定向表达式括起来,则变成了关系表达式,结果完全不一样。括号内最终的结果只会是1或0。当然这也可以是一种新的用法让我去解决其他需求。
[tyson@Tyson Lee testawk]$ awk '{ print $1,($2+1000>$3)}' text.txt
SR 1
Canada 1
China 1
USA 1
Brazil 1
India 1
Mexico 1
France 1
Japan 1
Germany 1
England 1
在awk程序中,不论是一个还是多个重定向符只会打开文件一次,也就是说打开前清除,直到awk程序结束之前才会停止追加内容。
所在在这种情况下,若awk程序中包含了>和>>重定向符且程序在执行到包含>>的语句时,并不会清空内容,所以会产生与shell中重定向符的使用不同的现象。
[tyson@Tyson Lee testawk]$ awk -F: '/tyson/{print $1>"textChong1.txt"};/tyson/{print $2>>"textChong1.txt"}' /etc/passwd
[tyson@Tyson Lee testawk]$ cat textChong1.txt
tyson
x
tyson1
x
若awk程序只包含了一个重定向符,那么两种不同的重定向符(覆盖和追加)的作用和在shell中的重定向符效果是一样的。这里不再演示。
例如使用awk分割字段后,与sort和uniq命令结合对nginx的日志文件进行分析,找出每个ip的访问次数。
实例:
[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]$ cat text.txt |awk '{print $4}'|sort -n
Asia
Asia
Asia
Asia
Europe
Europe
Europe
North_America
North_America
North_America
South_America
[tyson@Tyson Lee testawk]$ cat text.txt |awk '{print $4}'|sort -n|uniq -c
4 Asia
3 Europe
3 North_America
1 South_America
若要在awk里面用shell的命令,需要用在管道夫后面用双引号保卫shell命令
[tyson@Tyson Lee testawk]$ cat text.txt |awk '{print $4 | "sort -n"}'
Asia
Asia
Asia
Asia
Europe
Europe
Europe
North_America
North_America
North_America
South_America