awk内置函数、外部变量

外部变量
	①获取外部变量
	格式: 
	awk ‘{action}’ 变量名=变量值 ,这样传入变量可以在action中获得值。
	示例: 
	test='awk test'--day-5


外部变量
	①获取外部变量
	格式: 
	awk ‘{action}’ 变量名=变量值 ,这样传入变量可以在action中获得值。
	示例: 
	test='awk test'
	echo | awk  '{print string}' string="$test"
	结果: awk test

	echo | awk  string="$test" '{print string}'  --错误的定义方法
	结果: awk: cmd. line:1: fatal: cannot open file `{print string}' for reading (No such file or directory)
	注:变量名与值放到’{action}’后面,即 string="$test" 在 print 后面

	# a=100
	# b=200
	# echo | awk '{print num1+num2}' num1=$a num2=$b
	300


	②BEGIN程序块中变量
	格式:
	awk -v 变量名=变量值 [-v 变量2=值2 …] 'BEGIN{action}’ 
	示例:
	test='awk test'
	echo | awk -v string="$test" 'BEGIN{print string}'
	结果: awk test

	echo | awk -v string="$test" '{print string}'
	结果: awk test



 awk关系操作符
	==   等于
	!=   不等于
	>    大于
	<    小于
	>=   大于等于
	<=   小于等于

 awk逻辑操作符
	&&	逻辑与	类似shell里的[ 条件1 -a  条件2 ]
	||	逻辑或	类似shell里的[ 条件1 -o  条件2 ] 
	!	非





awk外部脚本

一. 脚本的结构

	#!/bin/awk -f

	BEGIN {

	}
		  {
	}

	END {

	}


	例:把awk -F: '{print $1}' /etc/passwd 改成写外部脚本的形式

	BEGIN {

		    FS=":"
	}
		    {
		    print $1
	}
	END {

	}

	# awk -f 1.awk /etc/passwd


二. 格式化输出
	格式化输出要使用printf函数

	awk 'BEGIN {printf()}'
	
	1) 类型
	类型字符用以表示输出数据的类型,其格式符和意义如下表所示:
	格式字符	意义
	d	以十进制形式输出带符号整数(正数不输出符号)
	o	以八进制形式输出无符号整数(不输出前缀0)
	x,X	以十六进制形式输出无符号整数(不输出前缀Ox)
	u	以十进制形式输出无符号整数
	f	以小数形式输出单、双精度实数
	e,E	以指数形式输出单、双精度实数
	g,G	以%f或%e中较短的输出宽度输出单、双精度实数
	c	输出单个字符
	s	输出字符串
	%	输出%


	# awk 'BEGIN{printf("%d\n",10)}'			--输出十进制数字
	# awk 'BEGIN{printf("%d\n",-10)}'			--输出十进制负数
	# awk 'BEGIN{printf("%o\n",10)}'			--八进制输出
	# awk 'BEGIN{printf("%x\n",10)}'			--十六进制输出
	# awk 'BEGIN{printf("%u\n",10)}'			--无符号十进制输出
	# awk 'BEGIN{printf("%f\n",3.14)}'			--输出小数
	# awk 'BEGIN{printf("%e\n",31.4)}'			--指数
	# awk 'BEGIN{printf("%g\n",31.4)}'
	# awk 'BEGIN{printf("%c\n","a")}'			--输出字符
	# awk 'BEGIN{printf("%s\n","haha")}'		--输出字符串
	# awk 'BEGIN{ i=50;j=60;k=70; printf("%d %o %x \n",i,j,k)}'
	# awk 'BEGIN{ i=50;j=60;k=70; printf("%d%%\t%o%%\t%x%%\n",i,j,k)}'

	2) 标志
	标志字符为 -、+、# 0和空格五种,其意义下表所示:
	标 志	意义
	-		结果左对齐,右边填空格
	+		输出符号(正号或负号)
	空格		输出值为正时冠以空格,为负时冠以负号
	#		对c、s、d、u类无影响;
			对o类,在输出时加前缀0;
			对x类,在输出时加前缀0x;
			对e、g、f 类当结果有小数时才给出小数点。
	0		填充0

	# awk 'BEGIN{printf("%5d\n",10)}'			--输出宽度,默认右对齐
	# awk 'BEGIN{printf("%-5d\n",10)}'			--左对齐
	# awk 'BEGIN{printf("%+5d\n",10)}'			--输出+/-号
	# awk 'BEGIN{printf("% d\n",10)}'			--输出值为正时冠以空格
	# awk 'BEGIN{printf("% d\n",-10)}'			--为负时冠以负号
	# awk 'BEGIN{printf("%#o\n",10)}'			--加前缀0
	# awk 'BEGIN{printf("%#x\n",10)}'			--加前缀0x
	# awk 'BEGIN{printf("%05d\n",10)}'			--填充0
	# awk 'BEGIN{printf("%02d:%02d:%02d\n",8,5,4)}'


	3) 精度
	精度格式符以“.”开头,后跟十进制整数。
	本项的意义是:如果输出数字,则表示小数的位数;如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。

	# awk 'BEGIN{printf("%.4f\n",3.14)}'		--小数点后保留4位
	# awk 'BEGIN{i=3.14; printf("%5.2f\n",i)}'	--5是宽度
	# awk 'BEGIN{printf("%08.2f\n"),3.1415926}'	--%08 代表共8位 .2f 代表小数点两位
	# awk 'BEGIN{printf("%.4s\n","hello")}'		--输出字符串,为字符个数


三. 字符匹配
	==  	完全精确匹配
	~		部分匹配
	!~      不匹配
	!=

	# awk -F: '$3==65534 {print $1}' /etc/passwd	--这是通过uid的值,找用户名,条件用到了数值的匹配
	nfsnobody
	# awk -F: '$1=="nfsnobody" {print $3}' /etc/passwd	--这反过来,匹配字符串,来查找其它内容;这里就要用到现在讲的字符匹配
	65534

	完全匹配
	awk -F: '$1=="oo" {print $0}' /etc/passwd

	部分匹配
	awk -F: '$1~"oo" {print $0}' /etc/passwd
	awk -F: '$1~/oo/ {print $0}' /etc/passwd
		
	不匹配
	awk -F: '$1!="oo" {print $0}' /etc/passwd
	awk -F: '$1!~"oo" {print $0}' /etc/passwd


	查找用户名里有a字母的用户个数

	awk -F: '$1~"a" {print $1}' /etc/passwd |wc -l


四. awk内置函数
	blength[([s])]			计算字符串长度(byte为单位)
	length[([s])]			计算字符串长度(character为单位)
	rand()					生成随机数
	srand([expr])			设置rand() seed
	int(x)					字符串转换为整型
	substr(s, m [, n])		取子字符串
	index(s, t)				在字符串s中定位t字符串首次出现的位置
	match(s, ere)			在字符串s中匹配正则ere,match修改RSTART、RLENGTH变量。
	split(s, a[, fs])		将字符串分割到数组中
	sub(ere, repl [, in])	字符串替换
	gsub					同上
	sprintf(fmt, expr, ...) 格式化输出		
	system(cmd)				在shell中执行cmd。
	toupper(s)				字符串转换为大写
	tolower(s)				字符串转换为小写

	长度函数:length()

	例:打印出/etc/passwd的所有用户名,并统计其字符长度
	awk -F: '{print $1"长度为"length($1)}' /etc/passwd

	例:查找出用户名长度大于5的用户,显示用户名
	awk -F: 'length($1)>5 {print $1}' /etc/passwd

	大小转换:toupper(),tolower()
	awk -F: '{print toupper($1)}' /etc/passwd
	awk -F: '{print tolower(toupper($1))}' /etc/passwd

	截取函数:substr()
	awk -F: '{print substr($1,1,2)}' /etc/passwd		--把$1从第一个字符开始,截取2个(而不是从第一个到第二个)
	# echo 12345356346343234sfsahaha34523 |awk '{print substr($0,index($0,"haha"),4)}'
	haha




	替换函数:
	sub()  	单替换
	gsub()  全替换

	# awk -F: 'NR==1 {sub("o","O",$0);print $0}' /etc/passwd 
	rOot:x:0:0:root:/root:/bin/bash

	# awk -F: 'NR==1 {gsub("o","O",$0);print $0}' /etc/passwd 
	rOOt:x:0:0:rOOt:/rOOt:/bin/bash

	# awk -F: 'NR==1 {gsub("/bin/bash","/sbin/nologin"); print $0}' /etc/passwd

	
五. 其他函数
	①算术函数:
	awk函数				描述
	cos(x)				返回x的余弦
	exp(x)				返回e的x次幂
	int(x)				返回x的整数部分
	log(x)				返回x的自然数对数(e为底)
	sin(x)				返回x的正弦
	aqrt(x)				返回x的平方根
	atan2(y,x)			返回y/x的反正切
	rand()				返回随机数
	srand(x)			建立rand()的新的种子数。如果没有指定种子数,就用当前时间。返回旧的种子值。
	
	
	②字符串函数
	gsub(r,s,t)			在字符串t中用字符串s替换和r匹配的所有字符串。返回替换的个数。如果没有指定t,默认$0。
	index(s,t)			返回子串t在字符串s中的位置,如果没有指定s,则返回0。
	length(s)			返回s字符串的长度。如果未给出s参数,则返回$0的长度。
	blength(s)			以字节为单位。
	substr(s,p,n)		返回字符串s中从位置p开始最大长度为n的子串。如果没有给出n,返回从p开始剩余的字符串		
	sub(r,s,t)			在字符串t中用s替换r的首次匹配。成功返回1,失败返回0,如果没有指定t,默认$0。
	split(s,a,sep)		使用字段分隔符sep将字符串s分解到数组a的元素中,返回元素的个数。如果没有指定sep,则使用FS。
	tolower(s)			将字符串s转换为小写,并返回新串
	toupper(s)			将字符串s转换为大写,并返回新串
	sprintf("fmt",expr)与printf格式相同

	③一般函数:
	getline			用户从输入中读取另一行。输入包括文件和管道的数据。成功读取一行返回1,读到结尾返回0,出错返回-1,与shell编程的read函数类似
	close			关闭打开的文件和管道
	system			执行一条系统命令

	从文件读,打开外部文件:
	# awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}'
	
	shell实现:
	# echo "Enter your name:"; read name; echo "Your name is "name

	调用外部应用程序:
	# awk 'BEGIN{b=system("ls -al");print b;}'




	④时间函数
	mktime( YYYY MM DD HH MM SS[ DST])		生成时间格式
	systime()								得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数
	strftime([format [, timestamp]])		格式化时间输出,将时间戳转为时间字符串

	strftime日期和时间格式说明符
	格式 描述
	%a	星期几的缩写(Sun)
	%A	星期几的完整写法(Sunday)
	%b	月名的缩写(Oct)
	%B	月名的完整写法(October)
	%c	本地日期和时间
	%d	十进制日期
	%D	日期 08/20/99
	%e	日期,如果只有一位会补上一个空格
	%H	用十进制表示24小时格式的小时
	%I	用十进制表示12小时格式的小时
	%j	从1月1日起一年中的第几天
	%m	十进制表示的月份
	%M	十进制表示的分钟
	%p	12小时表示法(AM/PM)
	%S	十进制表示的秒
	%U	十进制表示的一年中的第几个星期(星期天作为一个星期的开始)
	%w	十进制表示的星期几(星期天是0)
	%W	十进制表示的一年中的第几个星期(星期一作为一个星期的开始)
	%x	重新设置本地日期(08/20/99)
	%X	重新设置本地时间(12:00:00)
	%y	两位数字表示的年(99)
	%Y	当前月份
	%Z	时区(PDT)
	%%	百分号(%)

	例:
	# awk 'BEGIN{tstamp=mktime("2015 01 01 12 12 12");print strftime("%c",tstamp);}'
	# awk 'BEGIN{tstamp1=mktime("2015 01 01 12 12 12");tstamp2=mktime("2015 02 01 0 0 0");print tstamp2-tstamp1;}'

	# awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}' 
	
	# awk 'BEGIN{tstamp=systime(); print strftime("%c",tstamp)}'
	# awk 'BEGIN{tstamp=systime(); print strftime("%D",tstamp)}'
下面是这五个人的五次考试成绩
张三 75 82 63 90 88
李四 59 67 70 72 71
王五 90 98 94 89 95
马六 40 45 48 55 60
田七 64 68 70 73 66

1,求五人的平均成绩
2,对五人评级,平均90以上为A级,平均80-89为B级,平均70-79为C级,平均60-69为D级,平均60以下为E级
3,求全班所有的平均成绩和大于平均成绩的人数和小于平均成绩的人数


BEGIN { 
	sum=0
	count1=0
	count2=0
}
        {
	average=($2+$3+$4+$5+$6)/5
	sum=sum+average
	print $1"的平均分为"average
	avg_toal[NR]=average
	if (average >=90)
		print $1"评级为A"
	else if (average>=80 && average<90)
		print $1"评级为B"
	else if (average>=70 && average<80)
		print $1"评级为C" 
	else if (average>=60 && average<=70)
		print $1"评级为D"
	else  print $1"评级为E"
}
END {
	aver2=sum/5
	for(i=1;i<=NR;i++) {
		if (avg_toal[i]>=aver2) {
			count1+=1
		}
		else {
			count2+=1
		}
		}
 		print  "全班平均分为"aver2"\t""大于平均分的人数"count1"\t""小于平均分的人数为"count2
}

------------------------------------
#!/bin/awk -f

BEGIN{
        sum = 0
        cnt1 = 0
        cnt2 = 0
}
{
        avg = ($2+$3+$4+$5+$6)/5
        print $1"的平均成绩是:"avg
        avg_arr[NR] = avg

        if (avg >= 90)
                print $1"的等级是A"
        else if(avg >= 80 && avg < 90)
                print $1"的等级是B"
        else if(avg >= 70 && avg < 80)
                print $1"的等级是C"
        else if(avg >= 60 && avg < 70)
                print $1"的等级是D"
        else
                print $1"的等级是E"

        if( NR==5 )
        {
                for (i in avg_arr)
                {
                        sum = sum + avg_arr[i]
                }
                print sum/5

                for (j in avg_arr)
                {
                        if ( avg_arr[j] > sum/5 )
                                cnt1++
                        else
                                cnt2++
                }

                print "大于平均成绩的人数是"cnt1"个"
                print "小于平均成绩的人数是"cnt2"个"
        }
}
END{

}




3 5 6 7
2 3 1 0
4 5 6 9
2 3 4 4
2 2 1 0
4 5 0 9
假如把2列的3列的和做为新的第五列,第五列的平均值为avg5,求第5列中大于avg5的行数(要求用awk)

	#!/bin/bash

	BEGIN{
		    sum=0
		    cnt=0
	}
	{
		    print $0,$2+$3
		    sum=sum+$2+$3
		    array[NR]=$2+$3
	}
	END{
		    avg5=sum/NR
		    print avg5

		    for(i=1; i<=length(array);i++)
		    {
		            if(array[i] > avg5)
		                    cnt++
		    }

		    print cnt
	}

	用两步来做

	awk '{print $0,$2+$3}' 4.txt |awk 'BEGIN{sum=0} {sum=sum+$5} END {print sum/NR}'
	6.83333	--得到平均值avg5为6.83333

	awk '{print $0,$2+$3}' 4.txt | awk 'BEGIN{sum=0} $5>6.83333 {sum=sum+1} END {print sum}' 
	3	--得到最终结果




	另外的两种做法


	awk '{x+=$2+$3;a[NR]=$2+$3}END{y=x/NR;for(i in a){if(y<a[i])z++}print z}' file

	awk 'BEGIN{while(getline<"file"){x+=$2+$3;i++};y=x/i}{if($2+$3>y)z++}END{print z}' file


	#!/bin/awk -f

	BEGIN{
		    sum = 0
	}
	{
		    print $1,$2,$3,$4,($2+$3)
		    sum = sum + ($2+$3)
		    array[NR] = ($2+$3)

		    if( NR==6 )
		    {
		            print "avg5="(sum/6)
		            for (i=1; i<length(array); i++)
		            {
		                    if( array[i] > sum/6 )
		                            print i
		            }
		    }
	}
	END{

	}




aaAAaa bbbbbb 111111 
222222 CCCCCC DdDdDd
eEeEeE 333333 FFFfff
GGGGgg 444444 hhHHHH
iiiIII JJjjJj 555555

将其结果变为:
aaaaaa bbbbbb
cccccc dddddd
eeeeee ffffff
gggggg hhhhhh
iiiiii jjjjjj

cat 3.txt |awk -F: '{print tolower($0)}'|awk '{gsub(/[0-9]/,"",$0);print $0}' |awk '{print $1,$2}'

cat 3.txt |awk -F: '{print tolower($0)}'|sed 's/[[:digit:]]//g' |awk '{print $1,$2}'


cat 3.txt |awk '$1~"[a-Z]" {printf tolower(toupper($1))" "} $2~"[a-Z]" {printf tolower(toupper($2))" "} $3~"[a-Z]" {printf tolower(toupper($3))}{print "" }'


awk '{print tolower($0)}'  3.txt |awk '{if ($1~"[0-9]") {print $2,$3};if ($2~"[0-9]") {print $1,$3};if ($3~"[0-9]") {print $1,$2}}'

awk '{print tolower($0)}' 3.txt |awk 'NR==1 {print $1,$2} NR==2 {print $2,$3} NR==3 {print $1,$3} NR==4 {print $1,$3} NR==5 {print $1,$2}'

awk 'NR==1 {gsub(/A/,"a");print substr($0,1,14)} NR==2 {gsub(/C/,"c");{gsub(/D/,"d")};print substr($0,8,14)} NR==3 {gsub(/E/,"e");{gsub(/F/,"f")};print substr($0,1,6)substr($0,14,7)} NR==4 {gsub(/G/,"g");{gsub(/H/,"h")};print substr($0,1,6)substr($0,14,7)} NR==5 {gsub(/I/,"i");{gsub(/J/,"j")};print substr($0,1,13)}' 3.txt


给出的文件有三列,第一列是QQ号码,第二列是游戏等级,第三列是每一次的游戏时间(单位为秒)。
然后输出的要求:
第一列是QQ号码
第二列要求等级大于25
第三列就是游戏的总时间。


原文件格式如下:
# cat 1.txt
11111   25   8974
22222   50   5867
11111   25   8539
33333   24   9291
22222   50   4938
22222	50   1234	
44444	28   6524
33333   24   7854
55555   26   3255
66666   30   2355
55555   26   2352

#!/bin/bash

cat 1.txt | awk '{print $1}' | sort | uniq | while read qq
do
cat 1.txt |awk -F" " '($2>25 && $1=="'$qq'") {print $0}'|awk 'BEGIN {sum=0} {sum=sum+$3}END{print $1 " "$2" "sum}'|grep -v ^[[:blank:]]
done


	echo | awk  '{print string}' string="$test"
	结果: awk test

	echo | awk  string="$test" '{print string}'  --错误的定义方法
	结果: awk: cmd. line:1: fatal: cannot open file `{print string}' for reading (No such file or directory)
	注:变量名与值放到’{action}’后面,即 string="$test" 在 print 后面

	# a=100
	# b=200
	# echo | awk '{print num1+num2}' num1=$a num2=$b
	300


	②BEGIN程序块中变量
	格式:
	awk -v 变量名=变量值 [-v 变量2=值2 …] 'BEGIN{action}’ 
	示例:
	test='awk test'
	echo | awk -v string="$test" 'BEGIN{print string}'
	结果: awk test

	echo | awk -v string="$test" '{print string}'
	结果: awk test



 awk关系操作符
	==   等于
	!=   不等于
	>    大于
	<    小于
	>=   大于等于
	<=   小于等于

 awk逻辑操作符
	&&	逻辑与	类似shell里的[ 条件1 -a  条件2 ]
	||	逻辑或	类似shell里的[ 条件1 -o  条件2 ] 
	!	非





awk外部脚本

一. 脚本的结构

	#!/bin/awk -f

	BEGIN {

	}
		  {
	}

	END {

	}


	例:把awk -F: '{print $1}' /etc/passwd 改成写外部脚本的形式

	BEGIN {

		    FS=":"
	}
		    {
		    print $1
	}
	END {

	}

	# awk -f 1.awk /etc/passwd


二. 格式化输出
	格式化输出要使用printf函数

	awk 'BEGIN {printf()}'
	
	1) 类型
	类型字符用以表示输出数据的类型,其格式符和意义如下表所示:
	格式字符	意义
	d	以十进制形式输出带符号整数(正数不输出符号)
	o	以八进制形式输出无符号整数(不输出前缀0)
	x,X	以十六进制形式输出无符号整数(不输出前缀Ox)
	u	以十进制形式输出无符号整数
	f	以小数形式输出单、双精度实数
	e,E	以指数形式输出单、双精度实数
	g,G	以%f或%e中较短的输出宽度输出单、双精度实数
	c	输出单个字符
	s	输出字符串
	%	输出%


	# awk 'BEGIN{printf("%d\n",10)}'			--输出十进制数字
	# awk 'BEGIN{printf("%d\n",-10)}'			--输出十进制负数
	# awk 'BEGIN{printf("%o\n",10)}'			--八进制输出
	# awk 'BEGIN{printf("%x\n",10)}'			--十六进制输出
	# awk 'BEGIN{printf("%u\n",10)}'			--无符号十进制输出
	# awk 'BEGIN{printf("%f\n",3.14)}'			--输出小数
	# awk 'BEGIN{printf("%e\n",31.4)}'			--指数
	# awk 'BEGIN{printf("%g\n",31.4)}'
	# awk 'BEGIN{printf("%c\n","a")}'			--输出字符
	# awk 'BEGIN{printf("%s\n","haha")}'		--输出字符串
	# awk 'BEGIN{ i=50;j=60;k=70; printf("%d %o %x \n",i,j,k)}'
	# awk 'BEGIN{ i=50;j=60;k=70; printf("%d%%\t%o%%\t%x%%\n",i,j,k)}'

	2) 标志
	标志字符为 -、+、# 0和空格五种,其意义下表所示:
	标 志	意义
	-		结果左对齐,右边填空格
	+		输出符号(正号或负号)
	空格		输出值为正时冠以空格,为负时冠以负号
	#		对c、s、d、u类无影响;
			对o类,在输出时加前缀0;
			对x类,在输出时加前缀0x;
			对e、g、f 类当结果有小数时才给出小数点。
	0		填充0

	# awk 'BEGIN{printf("%5d\n",10)}'			--输出宽度,默认右对齐
	# awk 'BEGIN{printf("%-5d\n",10)}'			--左对齐
	# awk 'BEGIN{printf("%+5d\n",10)}'			--输出+/-号
	# awk 'BEGIN{printf("% d\n",10)}'			--输出值为正时冠以空格
	# awk 'BEGIN{printf("% d\n",-10)}'			--为负时冠以负号
	# awk 'BEGIN{printf("%#o\n",10)}'			--加前缀0
	# awk 'BEGIN{printf("%#x\n",10)}'			--加前缀0x
	# awk 'BEGIN{printf("%05d\n",10)}'			--填充0
	# awk 'BEGIN{printf("%02d:%02d:%02d\n",8,5,4)}'


	3) 精度
	精度格式符以“.”开头,后跟十进制整数。
	本项的意义是:如果输出数字,则表示小数的位数;如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。

	# awk 'BEGIN{printf("%.4f\n",3.14)}'		--小数点后保留4位
	# awk 'BEGIN{i=3.14; printf("%5.2f\n",i)}'	--5是宽度
	# awk 'BEGIN{printf("%08.2f\n"),3.1415926}'	--%08 代表共8位 .2f 代表小数点两位
	# awk 'BEGIN{printf("%.4s\n","hello")}'		--输出字符串,为字符个数


三. 字符匹配
	==  	完全精确匹配
	~		部分匹配
	!~      不匹配
	!=

	# awk -F: '$3==65534 {print $1}' /etc/passwd	--这是通过uid的值,找用户名,条件用到了数值的匹配
	nfsnobody
	# awk -F: '$1=="nfsnobody" {print $3}' /etc/passwd	--这反过来,匹配字符串,来查找其它内容;这里就要用到现在讲的字符匹配
	65534

	完全匹配
	awk -F: '$1=="oo" {print $0}' /etc/passwd

	部分匹配
	awk -F: '$1~"oo" {print $0}' /etc/passwd
	awk -F: '$1~/oo/ {print $0}' /etc/passwd
		
	不匹配
	awk -F: '$1!="oo" {print $0}' /etc/passwd
	awk -F: '$1!~"oo" {print $0}' /etc/passwd


	查找用户名里有a字母的用户个数

	awk -F: '$1~"a" {print $1}' /etc/passwd |wc -l


四. awk内置函数
	blength[([s])]			计算字符串长度(byte为单位)
	length[([s])]			计算字符串长度(character为单位)
	rand()					生成随机数
	srand([expr])			设置rand() seed
	int(x)					字符串转换为整型
	substr(s, m [, n])		取子字符串
	index(s, t)				在字符串s中定位t字符串首次出现的位置
	match(s, ere)			在字符串s中匹配正则ere,match修改RSTART、RLENGTH变量。
	split(s, a[, fs])		将字符串分割到数组中
	sub(ere, repl [, in])	字符串替换
	gsub					同上
	sprintf(fmt, expr, ...) 格式化输出		
	system(cmd)				在shell中执行cmd。
	toupper(s)				字符串转换为大写
	tolower(s)				字符串转换为小写

	长度函数:length()

	例:打印出/etc/passwd的所有用户名,并统计其字符长度
	awk -F: '{print $1"长度为"length($1)}' /etc/passwd

	例:查找出用户名长度大于5的用户,显示用户名
	awk -F: 'length($1)>5 {print $1}' /etc/passwd

	大小转换:toupper(),tolower()
	awk -F: '{print toupper($1)}' /etc/passwd
	awk -F: '{print tolower(toupper($1))}' /etc/passwd

	截取函数:substr()
	awk -F: '{print substr($1,1,2)}' /etc/passwd		--把$1从第一个字符开始,截取2个(而不是从第一个到第二个)
	# echo 12345356346343234sfsahaha34523 |awk '{print substr($0,index($0,"haha"),4)}'
	haha




	替换函数:
	sub()  	单替换
	gsub()  全替换

	# awk -F: 'NR==1 {sub("o","O",$0);print $0}' /etc/passwd 
	rOot:x:0:0:root:/root:/bin/bash

	# awk -F: 'NR==1 {gsub("o","O",$0);print $0}' /etc/passwd 
	rOOt:x:0:0:rOOt:/rOOt:/bin/bash

	# awk -F: 'NR==1 {gsub("/bin/bash","/sbin/nologin"); print $0}' /etc/passwd

	
五. 其他函数
	①算术函数:
	awk函数				描述
	cos(x)				返回x的余弦
	exp(x)				返回e的x次幂
	int(x)				返回x的整数部分
	log(x)				返回x的自然数对数(e为底)
	sin(x)				返回x的正弦
	aqrt(x)				返回x的平方根
	atan2(y,x)			返回y/x的反正切
	rand()				返回随机数
	srand(x)			建立rand()的新的种子数。如果没有指定种子数,就用当前时间。返回旧的种子值。
	
	
	②字符串函数
	gsub(r,s,t)			在字符串t中用字符串s替换和r匹配的所有字符串。返回替换的个数。如果没有指定t,默认$0。
	index(s,t)			返回子串t在字符串s中的位置,如果没有指定s,则返回0。
	length(s)			返回s字符串的长度。如果未给出s参数,则返回$0的长度。
	blength(s)			以字节为单位。
	substr(s,p,n)		返回字符串s中从位置p开始最大长度为n的子串。如果没有给出n,返回从p开始剩余的字符串		
	sub(r,s,t)			在字符串t中用s替换r的首次匹配。成功返回1,失败返回0,如果没有指定t,默认$0。
	split(s,a,sep)		使用字段分隔符sep将字符串s分解到数组a的元素中,返回元素的个数。如果没有指定sep,则使用FS。
	tolower(s)			将字符串s转换为小写,并返回新串
	toupper(s)			将字符串s转换为大写,并返回新串
	sprintf("fmt",expr)与printf格式相同

	③一般函数:
	getline			用户从输入中读取另一行。输入包括文件和管道的数据。成功读取一行返回1,读到结尾返回0,出错返回-1,与shell编程的read函数类似
	close			关闭打开的文件和管道
	system			执行一条系统命令

	从文件读,打开外部文件:
	# awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}'
	
	shell实现:
	# echo "Enter your name:"; read name; echo "Your name is "name

	调用外部应用程序:
	# awk 'BEGIN{b=system("ls -al");print b;}'




	④时间函数
	mktime( YYYY MM DD HH MM SS[ DST])		生成时间格式
	systime()								得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数
	strftime([format [, timestamp]])		格式化时间输出,将时间戳转为时间字符串

	strftime日期和时间格式说明符
	格式 描述
	%a	星期几的缩写(Sun)
	%A	星期几的完整写法(Sunday)
	%b	月名的缩写(Oct)
	%B	月名的完整写法(October)
	%c	本地日期和时间
	%d	十进制日期
	%D	日期 08/20/99
	%e	日期,如果只有一位会补上一个空格
	%H	用十进制表示24小时格式的小时
	%I	用十进制表示12小时格式的小时
	%j	从1月1日起一年中的第几天
	%m	十进制表示的月份
	%M	十进制表示的分钟
	%p	12小时表示法(AM/PM)
	%S	十进制表示的秒
	%U	十进制表示的一年中的第几个星期(星期天作为一个星期的开始)
	%w	十进制表示的星期几(星期天是0)
	%W	十进制表示的一年中的第几个星期(星期一作为一个星期的开始)
	%x	重新设置本地日期(08/20/99)
	%X	重新设置本地时间(12:00:00)
	%y	两位数字表示的年(99)
	%Y	当前月份
	%Z	时区(PDT)
	%%	百分号(%)

	例:
	# awk 'BEGIN{tstamp=mktime("2015 01 01 12 12 12");print strftime("%c",tstamp);}'
	# awk 'BEGIN{tstamp1=mktime("2015 01 01 12 12 12");tstamp2=mktime("2015 02 01 0 0 0");print tstamp2-tstamp1;}'

	# awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}' 
	
	# awk 'BEGIN{tstamp=systime(); print strftime("%c",tstamp)}'
	# awk 'BEGIN{tstamp=systime(); print strftime("%D",tstamp)}' 

猜你喜欢

转载自www.cnblogs.com/The-day-of-the-wind/p/12064485.html