详解awk(二)格式化输出与内置变量结合实现需求

目录

一、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特有的变量结合有诸多玩法。

 

一、awk的program中print的用法

1.1print函数语法

print expression1,expression2,...,expressionn
print (expression1,expression2,...,expressionn)

print的作用可以简述为,使用awk程序用默认的输出字段分隔符(内置变量OFS)将该函数中用逗号隔开的各表达式的字符串值分隔开并输出。

 

1.2打印输出每一行

当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

 

1.3 选择输出

  • 在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

 

1.4 为记录加上行号

内置变量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

 

1.5 用更美观的分隔符输出文件信息

更改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是不科学的,因为这样被记录整体作为一个字段输出,就没有讨论分隔的必要。

 

二、awk的program中printf的用法

2.1 函数语法

printf format,expression1,expression2,expressionn

printf (format,expression1,expression2,expressionn)

format是必须的,是一个变量,其字符串值包含字面文本(直接输出)和格式说明符

  • 字面字符:字面意义的字符,例如“the total is”

  • 格式说明符:百分号、对齐方式、字符串最大宽度格式控制字符、占用字符宽度,如“%-5c”

 

格式控制符

c

ASCII字符

d

十进制

e

科学计数法

f

浮点数

s

字符串

%

打印百分号

非常用格式控制符

g

 

o

无符号八进制数

x

无符号十六进制数

 

对齐方式:

连字符-表示左对齐,默认是右对齐。

 

字符串最大宽度:

用数值指定。需要注意的是这里指定的是能进行格式化输出的最大字符宽度,所以若需要输出的字符串宽度大于该值也不会截断,只是所指定的格式化输出的参数会失效。

 

 

2.2 输出重定向之输出到文件

默认情况下,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中的重定向符效果是一样的。这里不再演示。

 

2.3 输出重定向之输出到管道

例如使用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

 

你可能感兴趣的:(linux基础)