awk的基本使用--我的学习记录

Awk


名称来源: Aho Weinberger  Kernighan 三个开发者名字首字母,但现在我们使用的版本已经不是原始的AWK了。而是GUN组织后来编写的开源的,所以全名应该是GAWK

wKioL1VwOMyB93v0AABF3CY2cAI694.jpg

 

基本用法:

gawk[OPTIONS] 'program' FILE1 FILE2 ...

program: PATTERN{ACTION STATEMENT}

ACTION: print, printf

 

选项:

-F: 指明输入字段分隔符

-v VAR_NAME=VALUE: 变量赋值;

-f /PATH/FROM/AWK_SCRIPT

 

1awk的输出命令之一:print

 

用法:print item1, item2, ...

item可以为字符串,也可以为变量

wKiom1VwN12yDTFOAADAMJccVkU064.jpg

要点:

(1) item之间需要使用逗号分隔;而输出时的分隔符为默认为空白字符;

(2) 输出的各item可以为字符串或数值、当前记录的字段($#)、变量或awk的表达式;数值会被隐式转换为字符串进行输出;

(3) print后面的item省略时,相当于运行“print $0”,用于输出整行;

            wKioL1VwO3exYzcMAABCNFsUbJw874.jpg

(4) 输出空白字符:print " "

    wKioL1VwPA6zZszlAAAtlS9ydLA329.jpg


 

变量类型:

内置变量:

FS:输入分隔符,默认为空白字符

RS:输入换行符,默认为换行符

OFS:输出分隔符,默认为空白字符

ORS:输出换行符,默认为换行符

NF:当前行的字段数

print NF:显示当前字段数

Print $NF:显示最后一个字段

NR:行数;命令后跟的所有文件将统一计数

Print NR:显示行数

FNR:行数;各文件分别计数

FILENAME:当前正被awk读取的文件的文件名

ARGCawk命令行中的参数的个数(program不算参数)

ARGV:数组,保存了命令行参数(program不算参数)

awk '{print ARGV[0]}' /etc/passwd  :则显示第一个参数 awk

awk '{print ARGV[1]}' /etc/passwd  :则显示第二个参数/etc/passwd

 自定义变量:

-v VAR_NAME=VALUE

可在选项中定义变量;也可以在program中定义变量

awk  -vname=tom '{print name}' /etc/passwd

awk '{name="tom";print name}' /etc/passwd

 

 

2awk的输出命令之二:printf

 

语法:printf FORMAT,item1,item2,...

 

要点:

(1) 必须提供FORMAT

(2) print语句不同,printf不会自动换行,需要显式指定换行符:\n

(3) FORMAT中需要分别为后面的每个item指定一个格式符,否则item则无法显示;

wKioL1VwOSuCqcVGAACVcMUOUT0242.jpg

 

格式符:都以%开头,后跟单个字符;

%c: 显示字符的ASCII码;

%d, %i:显示为十进制整数;

%e, %E: 科学计数法显示数值;

%f:显示为浮点数;

%g, %G:以科学计数法或浮点数格式显示数值;

%s: 显示为字符串;

%u:显示无符号整数;

%%: 显示%符号自身;

 

修饰符:

#[.#]

左边的#:用于指定显示宽度;

右边的#: 显示精度;

+:显示数值符号

-:左对齐

wKioL1VwOmCxOTVeAADVAK3K2vI359.jpg

操作符

 

算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x: 负值

+x: 转换为数值

 

字符操作符:字符串连接 (空格)

 

赋值操作符:

=, +=, -=, *=, /=, %=, ^=

++, --

 

比较操作符:

>, >=, <, <=, ==, !=

 

模式匹配操作符:

~:是否能由右侧指定的模式所匹配;

!~:是否不能由右侧指定模式所匹配;

 

逻辑操作符:

&&:与运算

||: 或运算

 

条件表达式:

selector?if-true-expression:if-false-expression(若selector为真,则执行if-true-expression,若为假,则执行if-false-expression)

例如: awk -F: '{$3>=500?type="commonuser":type="sysuser";printf "%20s -is-%-s\n",$1,type}' /etc/passwd

wKioL1VwPJjj-FebAACVO7FzkO8559.jpg

 

函数调用:

function_name(argu1, argu2, ...)

 

PATTERN

 

(1)empty:空模式,匹配所有行;

 

(2)/Regular Expression/:仅将ACTION应用于能够被正则表达式所匹配到的行;

例如:awk '/^root/{print }' /etc/passwd  显示root这行

 

(3)relational expression:关系表达式,即结果为“真”、“假”的表达式,或者其结果能类同于“真”或“假”的表达;一般来说,其结果为非0数值或非空字符串即可类同为“真”,否则,则类同为“假”;

例如:awk -F: '$3>=500{print $1,$3}'/etc/passwd   显示UID大于等于500的,用户名和UID

例如:awk -F: '$1~/root/{print $1,$3}'/etc/passwd  显示第一个字段能和root匹配的用户名和UID

 

(4)line ranges:行范围,类似sedvim中的地址定界方式

startline,endline

 

(5)BEGIN/END:两个特殊模式

BEGIN:在文件格式化操作开始之前事先执行的一次操作;通常用于输出表头或做出一个预处理操作;

END:在文件格式操作完成之后,命令退出之前执行的一次操作;通常用于输出表尾或做出清理操作;

 

例子:awk 'BEGIN{print"xxxxxxxxxxxxxxxxxxxxxx"}{print "yyyyyyyyyyyyy"}END{print"xxxxxxxxxxxxxxxxxxxxx"}' /etc/fstab

BEGIN中的内容在{print"yyyyyyyyyyyyy"}之前执行一次

{print "yyyyyyyyyyyyy"}执行的次数为/etc/hosts文件的行数

END中的内容在{print"yyyyyyyyyyyyy"}之后执行一次

wKioL1VwPQ6xIUjhAAC3WYvdAjc950.jpg

 

常用ACTION

 

(1) EXPRESSIONS:条件表达式,例如变量赋值

(2) Control Statements:控制语句,如if, while等;

(3) Compound Statements:复合语句

(4) input statements:输入语句

(5) output statements:输出语句

 

控制语句

 

if (condition) { statements } [else { statement }]

 

while (condition) { statements }

 

do statement while (condition)

 

for(expr1;expr2;expr3) { statements }

 

for(var in array) { statements }

 

switch (expression) {case VALUE or /REGEXP/: statement;...; default: statementN}

 

break

 

continue

 

delete array[index]

 

delete array

 

exit [ expression ]

 

{ statements }

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

1 if-else条件判断

 

语法:if (condition) statement [ else statement ]

if (condition) {statements} [else {statements}]

 

wKiom1VwO7fDLE1yAAC7lZaJmw0465.jpg

 

使用场景:对awk取得的整行或行中的字段做条件判断;

 

2while循环

语法:while (condition) statement

while (condition) {statements}

 

条件为“真”时循环,为“假”时退出循环;

 

使用场景:通常用于在当前行的各字段间进行循环;

awk -F: '{i=1;while(i<=NF){if(length($i)>=6) {printf "%s %s",$i," "};i++};print" "}' /etc/passwd

wKioL1VwPXOyJQSyAADgT4fx2b4013.jpg

3do-while循环

语法:do statement while (condition)

do {statements} while (condtion)

意义:至少执行一次循环体

 

4for循环

语法:for (expr1;expr2;expr3) statement

for (expr1;expr2;expr3) {statements}

 

for (variable assignment;codition;iterationprocess) {for-body}

 

# awk '{for(i=1;i<=NF;i++){if(length($i)>=6)print $i}}' /etc/issue

            wKiom1VwPJXzdrk9AABhKqD-sm4231.jpg


 

第二种用法:用于遍历数组中的元素

for (var_name in array) {for-body}

 

5swtich

语法:switch (expression) {case VALUE or/REGEXP/: statement; ...; default: statementN}

 

6break and continue

break [n]:退出当前循环,n是一个数字,用于指定退出几层循环;

continue:提前结束本轮循环而进入下一轮;

wKioL1VwPaSTS27xAABnB41Y8Ko151.jpg

 

7next

提前结束对本行文本的处理,而提前进入下一行的处理操作;

 

# awk -F: '{if($3%2==0) next;print $1,$3}'/etc/passwd

 

 

数组

 

关联数组:array[index-expression]

 

index-expression

可以使用任意字符;

如果某数组元素事先不存在,则在引用时,awk会自动创建此元素并将其值初始化为空串;

因此,若要判断数组中的某元素是否存在,要使用“index in array”的方式进行判断;

要遍历数组中的元素,则要使用for (var_name in array)的方式进行;此时,var_name会遍历array的每个索引,所以,要显示数组元素的值,要使用array[var_name]

 

统计整个文件,每个单词出现的次数:

# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(j in count) {print j,count[j]}}'/root/count.txt                                        

每行单独统计,每个单词出现的次数:

# awk '{for(i=1;i<=NF;i++){count[$i]++};for(j in count) {print j,count[j]};delete count}' /root/count.txt

统计当前系统上所有tcp连接的各种状态的个数:

# ss -tan | awk'!/^State/{state[$1]++}END{for(i in state) print i,state[i]}'

统计指定的web访问日志中各ip的资源访问次数:

# awk '{ip[$1]++}END{for(i in ip) printi,ip[i]}' /var/log/httpd/access_log

 

 

 

函数:内建函数和用户自定义函数

 

内建函数

 

数值处理:

rand():返回01之间的一个随机数;

 

字符串处理:

length([s]):返回指定的字符串的长度;

sub(r,s[,t]):基于r所表示的模式来匹配字符串t中的内容,将其第一次被匹配到的内容替换为s所表示的字符串;

gsub(r,s[,t]):基于r所表示的模式来匹配字符串t中的内容,将其所有被匹配到的内容均替换为s所表示的字符串;

split(s,a[,r]):以r为分隔符去切割字符串s,并将切割后的结果保存至a表示的数组中;

 

例如:# awk'{split($0,userinfo,":");print userinfo[1]}' /etc/passwd   

首先用“:”分割/etc/passwd的每行,并保存在userinfo属组中,然后打印出userinfo数组第一个内容,即每行的用户名

注意:awk的数组下标从1开始编号

 

substr(s,i[,n]):从s所表示的字符串中取子串,取法:从i表示的位置开始,取n个字符;

 

时间类函数:

systime():取当前系统时间,结果形式为时间戳;

 

用户自定义函数

 

function f_name(p,q) {

...

}

 

 

 

 

 

 

 


你可能感兴趣的:(awk,文本处理工具)