linux awk简明笔记

awk是一个简单强大的文本过滤报告工具。

简介

其基本结构为pattern{action}

awk是一个面向行的编程工具。pattern定义了怎么匹配一个行,action定义了匹配成功的动作。默认为所有的行都匹配,BEGIN和END关键字,一个在所有行处理之前执行,一个在所有行处理之后执行。

awk把每一行看作一些field,$0代表整行,$1代表第一个field,等等。

和很多脚本语言不一样的是,$number不代表一个变量,而是一个field。

也不对""之中的符号进行特别解释。

换行不能乱用,可以

{action1}

{action2}

awk中有3种常量,字符串,数字,正则表达式。

数字和字符串的转换:

字符串转数字,贪婪算法转该字符串的顶头子字符串,如果不行为0。

数字转字符串,CONVFMT控制。整数不受CONVFMT控制。

awk的底层类型有两种,数字,字符串,一个变量可以既是数字,又是字符串,底层保有2个值。原因嘛,效率,精度。

运算符

比较的时候,使用的是最后赋值的类型,而不是最后使用的类型。

对于不确定类型(如传入参数,域)等,能数字比较的数字比较,不能的话变为字符串比较。

和c一脉相传的东西(很相似)

运算符

二元+-*/%<space><space>为字符串连接操作符。

一元+(正号)-(负号)

自增运算符++--

+=-=*=/=%=

=(赋值运算符)()可以明确运算符的优先级。

逻辑符

==!=>>=<<=

&&||!

检查一个字符串是否匹配

!~/正则表达式/不匹配正则表达式

~/正则表达式/匹配正则表达式

命令

if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( expression ; conditional ; expression ) statement
for ( variable in array ) statement
break
continue
{ [ statement ] ...}
variable=expression
print [ expression-list ] [ > expression ]
printf format [ , expression-list ] [ > expression ]
next  这个挺好用的,跳出当前处理的行。
exit   这个和一般的exit不同,跳过所有的行,但是会执行END。

内置常量

FS-TheInputFieldSeparatorVariable

用-F可以指定分隔符。FS是buildin的分隔符变量。

经典例子

行为OneTwo:Three:4Five

{
	print $2
	FS=":"
	print $2
}

输出Two:Three:4Five两次。

防止side-effect,FS的设置在readline之后有效,在一次readline之中变量不会改变,可以消除很多bug。

OFS-TheOutputFieldSeparatorVariable

NF-TheNumberofFieldsVariable

NR-TheNumberofRecordsVariable

RS-TheRecordSeparatorVariable

ORS-TheOutputRecordSeparatorVariable

FILENAME-TheCurrentFilenameVariable

AssociativeArrays

Insteadofusinganumbertofindanentryinanarray,useanythingyouwant.

关联数组的key全部都是string。

直接引用数组中不存在的key会创建一个pair。

用keyinarray可以测试该数组是否有一个key的pair并且不创建pair。

delete:删除元素。

BEGIN {
	username[""]=0;
}
{
	username[$3]++;
}
END {
	for (i in username) {
		if (i != "") {
			print username[i], i;
		}
	}
}

Multi-dimensionalArrays

a[1,2]=y;这个不行。

a[1","2]=y;记住,<space>是字符串连接。

ExampleofusingAWK'sAssociativeArrays

1记住初始化一个值。

2好的变量命名。

3确保输入正确。

4给每一个field起一个好名字。

5一遍遍历,得到所有东西。

一个好例子,值得好好研究,用户,组,文件所占空间大小检测程序。

#!/bin/sh
find . -type f -print | xargs /usr/bin/ls -islg | 
awk '
BEGIN {
# initialize all arrays used in for loop
	u_count[""]=0;
	g_count[""]=0;
	ug_count[""]=0;
	all_count[""]=0;
}
{
# validate your input
        if (NF != 11) {
#	ignore
	} else {
# assign field names
		inode=$1;
		size=$2;
		linkcount=$4;
		user=$5;
		group=$6; 

# should I count this file?

		doit=0;
		if (linkcount == 1) {
# only one copy - count it
			doit++;
		} else {
# a hard link - only count first one
			seen[inode]++;
			if (seen[inode] == 1) {
				doit++;
			}
		}
# if doit is true, then count the file
		if (doit ) {

# total up counts in one pass
# use description array names
# use array index that unifies the arrays

# first the counts for the number of files

			u_count[user " *"]++;
			g_count["* " group]++;
			ug_count[user " " group]++;
			all_count["* *"]++;

# then the total disk space used

			u_size[user " *"]+=size;
			g_size["* " group]+=size;
			ug_size[user " " group]+=size;
			all_size["* *"]+=size;
		}
        }
}
END {
# output in a form that can be sorted
        for (i in u_count) {
				if (i != "") {
        	        print u_size[i], u_count[i], i;
				}
        }
        for (i in g_count) {
				if (i != "") {
        	        print g_size[i], g_count[i], i;
				}
        }
        for (i in ug_count) {
				if (i != "") {
        	        print ug_size[i], ug_count[i], i;
				}
        }
        for (i in all_count) {
				if (i != "") {
        	        print all_size[i], all_count[i], i;
				}
        }
} ' | 
# numeric sort - biggest numbers first
# sort fields 0 and 1 first (sort starts with 0)
# followed by dictionary sort on fields 2 + 3
sort +0nr -2 +2d | 
# add header
(echo "size count user group";cat -) |
# convert space to tab - makes it nice output
# the second set of quotes contains a single tab character
tr ' ' '	' 
# done - I hope you like it

note

note:虽然是脚本,但是防错,注释,明确初始值等等好的脚本编程习惯还是挺有用的。

相关推荐