awk所有常用语法

awk [OPTIONS] PROGRAM FILE...

选项:
	-F 指定分隔符
	-f 引用awk脚本
	-v VAR=VALUE 定义一个变量传递给PROGRAM,但是这里的变量BEGIN读不了,只有PROGRAM和END才能读。

PROGRAM由“ PATTERNS{ACTION;ACTION...} ”组成
	PATTERNS和ACTION可以其中一个不写
	PATTERNS不写表示所有记录。
    ACTION不写默认为print $0
 
记录(record)和字段(filed):
	记录是根据RS变量的值分割,默认情况下是换行符,也就是一行就是一个记录。
	字段是根据FS变量的值定义的,用于分割记录成字段。

引用记录的字段:
	$0 代表整个记录
	$1 第一个字段
	$N 第N个字段
    
AWK的变量:
	1、内建变量,由AWK自身内置的一些变量。
		FILENAME: 文件名。
		FS:字段分隔符,默认是空格和制表符。
		OFS:每个字段默认的输出分割符号。
		RS:记录分隔符,默认是换行符。
		ORS:每个记录默认的输出分割符号。
		NR:当前记录所在的行号(多个文件时会重置行号)
		FNR:当多个文件时不会重置行号。
		NF:当即字段的段号。
		IGNORECASE:匹配时是否忽略大小写。
		RLENGTH:由match函数所匹配到的子字符串的长度。
		RSTART:由match函数所匹配到的子字符串的起始位置
		
	2、用户自定义变量
		·通过”awk -v 变量名=变量值“ 定义并使用。
		·在ACTION内部直接定义。
		变量的值可以使用0开头表示8进制,0x开头表示16进制。
		
	使用变量:
		不管时内建变量还是用户自定义变量,直接写变量名即可,不需要加”$“符号来引用变量。
		但是for循环内的变量需要加”$“来引用。
		

PATTERNS: 用于对判断是否对当前记录应用ACTION
	这里的PATTERN不单单可以使用正则表达式,还可以是条件判断等。
	具体如下:
		1、/正则表达式/
		2、/正则/ && /正则/
		3、/正则/ || /正则/
		4、PATTERN ? PATTERN : PATTERN #(三元运算符)
		5、!PATTERN # 取反
		6、PATTERN,PATTERN # 多个PATTERN
		7、BEGIN 
		8、END
		9、 匹配操作符 
			~ PATTERN 匹配指定正则表达式 
			!~ PATTERN 不匹配指定正则表达式
		10、算数运算符
			++ -- 
			+= -= *= /= %=
			+ - * / % 
		11、逻辑运算
			&& 
			|| 
			!
			
			awk -F: '$1~/^r/ && $3>1000{print $0}' /etc/passwd
			
		12、(PATTERN) 优先计算括号内的表达式
			如: awk -F: '!($3>1000){print $1,$3}'
		

ACTION:
	print ITEM,ITEM... :  # 打印文本,ITEM之间默认用OFS变量的值隔开输出。
	print ITME,ITEM... >file # 打印文本并覆盖重定向到file。
	print ITME,ITEM... >>file # 打印文本并追加重定向到file。 
	printf("format",ITEM,ITEM...) [>file] : # 格式化打印文本。
	printf("format",ITEM,ITEM...) [>>file] # 格式化打印文本并追加重定向到file。 
		format的组成:
			%[修饰符号]控制字母
			
			控制字母:
                s 字符串
                d 或 i 整数型
                f 浮点数
                o 八进制
                x 十六进制
                
             修饰符号:
             	width: 指定输出的长度,不足则使用空格填充,如果超过指定长度则按实际长度输出。
             	- : 左对齐
             	.prec : prec时具体小数点的位数,会四舍五入。
                	如:awk -v NUM=2.2356 'BEGIN{printf("%.2f",NUM)}'
                	
AWK的数组:
	AWK的数组本质上都是关联数组,虽然你可以使用0123这类数字,看上去也很想index类型数组。但是本质还是关联数组。
	
	定义数组:
		变量名[INDEX]=VALUE
		INDEX: 可以是整数,也可以是字符串。
		
		arr["name"]="zhangsan"
		arr[2]=88
		arr["age"]=18
		
	引用数组:
		数组名[index]
	
	判断数组是否存在元素:
		if ( index in 数组变量名)
		
		arr["name"]="zhangsan"
		if( "name" in arr){
			print(arr["name"])
		}
	
	遍历数组:#使用特殊的for循环进行遍历
		# for循环遍历出来的是数组中的index,而不是数组index对应的值。这点和bash的数组不一样,但是和javascript一样。
		for(变量名 in 数组变量名){
			print(数组变量名[变量名])
		}
	
	删除数组:
		delete 数组变量名[index] # 删除数组的某个元素
		delete 数组变量名 # 删除整个数组

结构化语句if:
	# 只有if时可以写在同一行,并不写花括号
	if(condition)  statement1
	# 但是如果由else就必须写花括号
	if(condition){
		statement1
	}[else{
		statement2
	}]

结构化语句while和do while:
	
	while(condition){
		statements
	}
	
	do{
		statements
	}while(condition)

结构化语句for循环:
	for(变量;条件;自增){
		#for循环内部引用循环内局部变量要使用$
	}

循环控制break和continue:
	break:跳出循环
	continue:结束当前此次循环二进入下一次循环
	
控制语句exit:
	exit 是用来结束awk自身的循环,如果有些END{}语句则处理END语句,没有就结束了。
	
控制语句next:
	next 使awk自身循环提前结束对本行的处理而直接进入下一行。
	 awk -F: '{if($3%2!=0){next}; print $1,$3}' /etc/passwd
	 
# AWK函数:

数学函数:
	int(x)  对X进行floor运算。(地板)
	sqrt(x) X的平方根
	
随机数函数:
	srand([x]) 生产随机数种子
	rand() 返回随机数,0-1之间。
	
字符串函数:
	length([str]) #返回给定字符串的长度,如果没有参数则返回$0的长度
	index(str,T) #返回T在str中第一次出现的index位置。
	match(str,regex[,A]) # 返回str中匹配正则表达式regex出现的index位置。如果指定了数组A,会将匹配的部分存储进去。
	sub(regex,replace[,T])  # 如果指定了T则在T中根据正则regex查找第一次匹配的字符串并替换为replace,否则在$0中查找并替换。
	gsub(regex,replace[,T]) # 和上面的唯一不同是,将匹配的所有字符串都会替换。
	substr(str,i[,number]) # 返回字符串s从出现第一个i到number之间的字符串,如果没有number则为字符串S的尾部。
	split(str,arr[,regex]) # 根据FS变量或正则regex(如果指定了的话)分割字符串s并存储到数组a中。
	sprintf(format,variables) # 根据给定的variables和format来返回一个类似printf的字符串。
	tolower(str) # 转换为小写
	toupper(str) # 转换为大写

数组排序和判断:(自然排序)
	asort(arr [,dest_arr]) #将arr的值进行排序,然后将index重置为1、2、3形式,如果指定了dest_arr则保存到dest_arr中,否则会改变原arr。
	asorti(arr [,dest_arr]) # 根据arr的index进行排序,并保存到dest_arr中(如果指定了,否则会改变原arr)
	isarray(arr) # 判断给定的变量是否为数组类型

时间函数:
	mktime(datestr) # 将给定的datestr(YYYY MM DD HH MM SS [DST])转换为时间戳
	strftime(format [,timespamp]) # 将当前时间或给定的timestamp转换为日期。
	systime() # 返回当前时间的时间戳。
	
#自定义函数,必须写在BEGIN{}之前
function 函数名([参数名]){
	[return xxx] 
}

AWK 中I/O操作的语句:

getline的用法:
	geline会返回下面的值:
		1 如果还有下一行可以读取
		0 文件的尾部
		-1 表示出现错误,可以打印ERRNO查看出错的详细内容。
	getline #读取用户输出文本存储到$0
	getline <file #读取file用作下一个记录
		awk 'BEGIN{print "请输入姓名";getline input<"-";print input}'
	getline var #读取awk自身循环的下一行记录并赋值给var
		awk -F: '{getline str;print str}' /etc/passwd #你会发现passwd文件的第一行并没有打印。
	getline var <file #读取file的每一行并赋值给var
	command | getline [var] # 将shell命令的标准输出保存到$0或者给定的var变量中。
		awk -F: 'BEGIN{"id root"|getline;print}'

fflush([file]) 刷新与打开的输出文件或管道文件相关联的任何缓冲区。如果文件丢失或为空字符串,则刷新所有打开的输出文件和管道。

system("命令")函数
	运行给定的命令,如果命令会自动打印输出awk也会输出,不需要特意去print,然后该函数返回运行命令的退出状态$?。
	awk 'BEGIN{var=system("id -un root");print var}'

print和printf有关IO重定向的用法:
    print ... >> file 
    print ... > file 
    print ... | command
        awk -F: 'BEGIN{print "fuck" | "cat &> /tmp/aa.txt"}'
    printf也是类似的。
    
 特殊文件:
 /dev/stdin
 /dev/stderr
 /dev/stdout
 /dev/fd/N
 	用法示例:
 		将print打印出错误
 		awk 'BEGIN{print "fuck" > "/dev/strerr"}'
posted @ 2021-03-14 16:29  蕝戀  阅读(391)  评论(0编辑  收藏  举报