- 操作系统
- Linux
- 开发语言
- C/C++
- 开源协议
- GPL
-
awk
2014-10-09 14:42:05awkawk的使用:
移动文件:ls -lrt|awk '{ if( substr($8,6,8) == '20111029' && substr($8,26,3) == 'unl' ) print "mv "$8" /home/etl/data/interface;" }'|ksh
求和: awk '{sum+=$1}END{print sum}'
删除文件:ls -lrt|awk '{ if( substr($8,4,8) == '20111029' ) print "rm "$8" /home/etl/data/interface;" }'|ksh
find ./ -name "*20111113*" | awk '{print "rm " $1}' | ksh
查找文件:find . -name "*sms20111201*.unl" |xargs awk -F'|' '{if ($39 == '-1') print FILENAME"|"$0}'
-
AWK
2019-06-06 23:35:35一.AWK基本概念 1.基本用法 1.Centos中的文本处理工具 1)grep,egrep,fgrep:基于pattern(模式)的文本过滤工具 2)sed:流编辑器,行编辑器;通过模式空间,保持空间实现编辑 3)AWK:报告生成器,实现格式化...一.AWK基本概念
1.基本用法
1.Centos中的文本处理工具
1)grep,egrep,fgrep:基于pattern(模式)的文本过滤工具2)sed:流编辑器,行编辑器;通过模式空间,保持空间实现编辑
3)AWK:报告生成器,实现格式化文本输出
gawk - pattern scanning and processing language:基于模式扫描以及语言处理 1.AWK: Aho, Weinberger, Kernighan --> New AWK, NAWK 2.现如今一般使用的是GNU awk,即为gawk awk实际为gawk的符号链接 [root@sakura ~]# which awk /usr/bin/awk [root@sakura ~]# ls -l /usr/bin/awk "lrwxrwxrwx. 1 root root 4 5月 6 16:16 /usr/bin/awk -> gawk"
ps:gwak是一种过程式编程语言。gwak还支持条件判断,数组,循环等各种编程语言中所有可以使用的功能,因此可以将其称为一种脚本语言解释器。
2.基本用法:gawk [options] 'program' FILE ...
1)program:pattern{action statements}1.program:编程语言 2.pattern:模式 3.action statements:动作语句,可以由多个语句组成,各个语句间使用分号分隔;例如print;pringtf
2)-F选项:指明输入时用到的字段分隔符
3)-v var=value:自定义变量
4)awk在处理文本时也是一次读取一行,根据分隔符来进行切片,将分割出来的每一片都保存在awk的内部变量中,其分别为$1,$2,$3…以此类推至最后一个变量
3.print:print item1,item2,....;awk的输出命令之一
1)1)item:字符串,用引号引用,并且各item之间需要使用,隔开;例如print “kasumi”,“world”[root@sakura ~]# awk -F: '{print $1,$3}' /etc/passwd root 0 bin 1 daemon 2 若各item间未使用,隔开,则会将$1$3连续输出 [root@sakura ~]# awk -F: '{print $1 $3}' /etc/passwd root0 bin1 [root@sakura ~]# awk -F: '{print $1$3}' /etc/passwd root0 bin1 ps:其输出时默认的分隔符为空白字符
2)输出的各item可以当字符串,也可以是数值;当前记录的字段,变量或awk的表达式;数值会被隐式转换为字符串进行输出
字符串 item为字符串时需要使用" ",若将$1写入" "中,则不会引用awk内部变量 [root@sakura ~]# awk -F: '{print "kasumi:",$1,$3}' /etc/passwd kasumi: root 0 kasumi: bin 1 [root@sakura ~]# awk -F: '{print "kasumi:$1"}' /etc/passwd kasumi:$1 数值 item为数值时不需要" " [root@sakura ~]# awk -F: '{print 516,$1,$3}' /etc/passwd 516 root 0 516 bin 1 当前记录的字段 [root@sakura ~]# awk -F: '{print $1,$7}' /etc/passwd root /bin/bash bin /sbin/nologin 变量 ietm为变量时不需要使用$ [root@sakura ~]# awk -v path=kasumi 'BEGIN{print path}' kasumi
3)如果省略item,则相当于$0,即输出整行
[root@sakura ~]# awk -F: '{print}' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin
4)输出空白字符:print “”
[root@sakura ~]# tail -2 /etc/passwd | awk '{print ""}' ps:其表示为每处理一行信息,就输出空白字符
4.awk内建变量
1)FS:input field seperator,输入字段分隔符,与-F选项作用相同,默认为空白字符[root@sakura ~]# awk -v FS=":" '{print $1,$3}' /etc/passwd root 0 bin 1
2)OFS:output field seperator,输出时分隔字符,默认为空白字符
[root@sakura ~]# awk -v FS=":" -v OFS=":" '{print $1,$3}' /etc/passwd root:0 bin:1
3)RS:input record seperator,输入时得换行符,默认为\n换行符
[root@sakura ~]# awk -v RS=":" '{print}' /etc/passwd root x 0 0 ps:文本本身自带的\n换行符也会启换行作用
4)ORS:utput record seperator,输出时的换行符,默认为\n换行符
[root@sakura ~]# awk -v RS=":" -v ORS="#" '{print}' /etc/passwd root#x#0#0#root#/root#/bin/bash bin#x#1#1#bin#/bin#/sbin/nologin
5)NF:number of field,字段数量
1.NF 每行按分隔符计量的字段数 [root@sakura ~]# awk -F" " '{print NF}' /etc/fstab 0 1 2 2.$NF 表示仅显示每行最后一个字段,NF会被替换为每行的字段数量 [root@sakura ~]# awk -F" " '{print $NF}' /etc/fstab # /etc/fstab 2019
6)NR:number of record,统计行数,即给每行显示行数;命令后跟的所有文件将统一合并计数
[root@sakura ~]# awk '{print NR}' /etc/fstab /etc/issue 1 2 3 ps:若命令后跟多个文件,其行数不会分别显示
7)FNR:各文件分别计数;行数
[root@sakura ~]# awk '{print FNR}' /etc/fstab /etc/issue
8)FILENAME:当前文件名
[root@sakura ~]# awk '{print FILENAME}' /etc/issue /etc/issue /etc/issue /etc/issue [root@sakura ~]# awk 'FNR==1{print FILENAME}' /etc/issue /etc/fstab /etc/issue /etc/fstab ps:需要注意,指定文件有多少行,就会显示多少行文件名,使用操作符FNR==1可仅显示一行文件名
9)ARGC:命令行参数的个数
[root@sakura ~]# awk '{print ARGC}' /etc/fstab /etc/issue 3
10)ARGV:表示数组,保存的是命令行所给定的各个参数
[root@sakura ~]# awk 'NR==1{print ARGV[0]}' /etc/fstab /etc/issue awk [root@sakura ~]# awk 'NR==1{print ARGV[1]}' /etc/fstab /etc/issue /etc/fstab [root@sakura ~]# awk 'NR==1{print ARGV[2]}' /etc/fstab /etc/issue /etc/issue ps:程序段不会记录于其数组中
5.aw自定义变量
1)使用选项定义变量;-v var=value;变量名区分字符大小写[root@sakura ~]# awk -v stars=yuki '{print stars}' /etc/issue yuki yuki yuki ps:这里文件内容未起作用,但是使用了文件的行数
2)在program中直接定义变量
[root@sakura ~]# awk 'BEGIN{FS=":";f1=3}{print $f1}' /etc/passwd 0 1 [root@sakura ~]# awk 'BEGIN{stars="yuki";print stars}' yuki
6.printf格式化输出命令:awk的输出命令之二
1)语法:printf FORMAT, item1, item2, …1.FORMAT必须要给出 2.printf不会自动实现换行,需要显示给出换行控制符,\n 3.FORMAT中需要分别为后面的每个item指定一个格式化符号
2)格式符对照表
格式符 含义 %c 显示字符的ASCII码 %d,%i 显示十进制整数 %e,%E 科学计数法数值显示 %f 显示为浮点数 %g,%G 以科学计数法或浮点形式显示数值 %s 显示为字符串 %u 显示为无符号整数 %% 显示%自身 3)修饰符
1.#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;例如,%3.1f,显示为浮点数 2.-:表示左对齐 3.+:显示数值的符号 ps:默认为右对齐
4)练习
使用printf控制符 [root@sakura ~]# awk -F: '{printf "usernmae:%s,UID:%d\n",$1,$3}' /etc/passwd usernmae:root,UID:0 usernmae:bin,UID:1 usernmae:daemon,UID:2 ps:运行时会将$1,$3分别对应至%s,%d上
使用printf修饰符 [root@sakura ~]# awk -F: '{printf "usernmae: %-15s,UID: %d\n",$1,$3}' /etc/passwd usernmae: root ,UID: 0 usernmae: bin ,UID: 1 %-15s表示为,左对齐,%s的宽度为15
7.操作符
1)算术操作符:1.x+y, x-y, x*y, x/y, x^y, x%y 2.-x:转换为负数 3.+x:将字符串转换为数值
2)字符串操作符:没有符号的操作符,表示为字符串连接
3)赋值操作符
1.=, +=, -=, *=, /=, %=, ^= 2.++, --
4)比较操作符
>, >=, <, <=, !=, ==
5)模式匹配符
1.~:是否被模式所匹配 2.!~:是否被模式不匹配
6)逻辑操作符
1.&& 2.|| 3.!
7)函数调用
function_name(argu1,argu2,....)
8)条件表达式
selector?if-true-expression:if-false-expression
9)练习判断/etc/passwd文件中每个用户的UID,若其大于1000则显示common user,否则显示sysuser or sysadmin
[root@sakura ~]# awk -F: '{$3>=1000?usertype="common user":usertype="sysuser or sysadmin";printf "%15s:%-s\n",$1,usertype}' /etc/passwd root:sysuser or sysadmin bin:sysuser or sysadmin daemon:sysuser or sysadmin
8.PATTERN:模式
1)empty:空模式,匹配所有行2)/regular expression/:仅处理能够被此处的模式匹配到的行
[root@sakura ~]# awk '/^UUID/{print $1}' /etc/fstab UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f UUID=274b447f-b701-439b-908a-f328de77cf63 UUID=f9fc6d2d-a8d1-4f08-9aba-8999f3da565c UUID=362e5f41-bc95-46ff-9902-d4e5c634ad99 [root@sakura ~]# awk '!/^UUID/{print $1}' /etc/fstab # # [root@sakura ~]# awk -F: '/^[ab]/{print $1,$3}' /etc/passwd bin 1 adm 3 abrt 173
3)relational expression 关系表达式:结果有“真”或“假”;结果为“真”才会被处理;
结果为非0数值或非空字符串,即可认为是"真"[root@sakura ~]# awk -F: '$3>=1000{print $1,$3}' /etc/passwd nfsnobody 65534 yuki 1000 tom 1001 [root@sakura ~]# awk -F: '$1~/root/{print $1,$3}' /etc/passwd root 0 [root@sakura ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd root /bin/bash yuki /bin/bash [root@sakura ~]# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd root /bin/bash yuki /bin/bash tom /bin/bash
4)line ranges:行范围
1.startlin,endline:/part1/,/part2/ [root@sakura ~]# awk -F: '/^root/,/^adm/{print $1}' /etc/passwd root bin daemon adm 2.基于行数判断 [root@sakura ~]# awk -F: '(NR>=1&&NR<=5){print $1}' /etc/passwd root bin daemon adm lp ps:不支持直接给出数字的格式
5)BEGIN/END模式
1.BEGIN{}:仅在开始处理文件中的文本之前执行一次 2.END{}:仅在文本处理完成之后执行一次 [root@sakura ~]# awk -F: 'BEGIN{print " username uid \n-----------------"}{printf "%-10s %10d\n",$1,$3}END{print "===========\n end "}' /etc/passwd username uid ----------------- root 0 bin 1 daemon 2 . . . abc8 1013 abc9 1014 abc10 1015 =========== end
9.常用的action
1.Expressions(表达式) 2.Control statements:if, while等 3.Compound statements:组合语句(将多个语句当做当个代码块运行,多个语句需要使用{}) 4.input statements 5.output statements
二.控制语句
1.常用控制语句格式
1.if(条件:condition) {条件为真时语句:statments} 2.if(condition) {statments} else {statements} (双分支语句,组合语句中若有一个以上语句需要使用{},否则可以省略{}) 3.while(conditon) {statments} 4.do {statements} while(condition) (不论条件是否为真,都先循环一次循环体) 5.for(expr1;expr2;expr3) {statements} 6.break 7.continue 8.delete array[index] (从数组中删除指定语句) 9.delete array 10.exit (退出语句) 11.{ statements }
2.if-else语句:if(condition) {statement} else {statement}
1)判断/etc/passwd文件中每个用户的UID,若其大于1000则显示common user,否则显示sysuser or sysadminprint打印 [root@sakura ~]# awk -F: '{if($3>=1000){print "common user:",$1,$3}else{print "sysuser or sysadmin:",$1,$3}}' /etc/passwd sysuser or sysadmin: root 0 sysuser or sysadmin: bin 1 common user: abc9 1014 common user: abc10 1015 printf打印 [root@sakura ~]# awk -F: '{if($3>=1000){printf "common user: %s,%d\n",$1,$3}else{printf "sysuser or sysadmin: %s,%d\n",$1,$3}}' /etc/passwd sysuser or sysadmin: root,0 sysuser or sysadmin: bin,1 sysuser or sysadmin: daemon,2 common user: abc9,1014 common user: abc10,1015
2)判断/etc/passwd文件中每个用户的的bash是否为/bin/bash,并输出
[root@sakura ~]# awk -F: '{if($NF=="/bin/bash"){print $1,$NF}}' /etc/passwd root /bin/bash yuki /bin/bash tom /bin/bash
3)判断/etc/fstab文件中每行的字段是否大于5,大于5的话则输出整行
[root@sakura ~]# awk '{if(NF>=5){print $0}}' /etc/fstab # Created by anaconda on Mon May 6 16:16:15 2019 # Accessible filesystems, by reference, are maintained under '/dev/disk'
4)判断df -h命令显示的文件系统用量中,已用量超过20%的分区,并显示之
[root@sakura ~]# df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=20){print $1,$NF}}' /dev/sda3 44 /dev/sda2 26
ps:使用场景为,对awk取得的 整行或某个字段做条件判断
3.while循环:while(condition){statement};条件为真时进入循环,条件为假时,退出循环
1)判断/etc/grub2.cfg中,linux16开头的行中的每个单词的字符数[root@sakura ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.673.10.67.2-el7 29 root=UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f 46 ro 2
2)判断/etc/grub2.cfg中,显示linux16开头的行中的每个单词的字符数大于等于7的单词
[root@sakura ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=7){print $i,length($i)};i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.673.10.67.2-el7 29 root=UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f 46 crashkernel=auto 16 LANG=en_US.UTF-8 16 linux16 7
3)列出/etc/grub2.cfg文件中,当前系统可使用的内核,并对其编号
[root@sakura ~]# awk -F\' '/^menuentry/{print i++":",$2}' /etc/grub2.cfg 0: CentOS Linux (3.10.673.10.67.2-el7) 7 (Core) 1: CentOS Linux (3.10.67linux-3.10.67-1-el7) 7 (Core) 2: CentOS Linux (3.10.0-693.el7.x86_64) 7 (Core) 3: CentOS Linux (0-rescue-114408c9377741bc91b9e27df3c651f0) 7 (Core)
ps:对一行内的多个字段逐一做类似处理时使用;对数组中的各元素逐一处理时使用
4.do-while循环:do {statement}while{condition}
1)意义为:在进入while循环前,至少运行一次循环体5.for循环:for(expr1;expr2;expr3){statement}
1)语法:for(variable assignment;condition;iteration process) {for-body}2)判断/etc/grub2.cfg中,linux16开头的行中的每个单词的字符数
[root@sakura ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.673.10.67.2-el7 29 root=UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f 46 ro 2 crashkernel=auto 16
3)特殊用法:能够实现遍历数组中的元素
语法:for(var in array){for-body}
6.switch语句(类似bash shell中的case语句)
1)语法:switch(expression){case VALUE1 or /REGEXP/:statement;case VALUE2 or /REGEXP/:statement;…;default:statement}
ps:VALUE1 or /REGEXP为变量值或正则表达式能匹配到的内容;default为当所有选项不匹配时,显示的结构7.break和continue
1)break [n]:可跳出n层循环
2)continue:提前结束本轮循环,进入下轮循环8.next:跳出awk的内置循环,即提前结束对本行的处理而直接进入下一行
1)输出/etc/passwd文件中用户ID为偶数的用户,使用next实现[root@sakura ~]# awk -F: '{if($3%2!=0){next}else{print $1,$3}}' /etc/passwd root 0 daemon 2 lp 4 shutdown 6 mail 8 ps:使用awk -F: '{if($3%2!=0)next;print $1,$3}' /etc/passwd也可以实现
三.array数组
1.awk中一般使用关联数组:array[index-expression]
1)index-expression,数组索引1.可使用任意字符串;字符串需要使用双引号 2.如果某数组元素实现不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串” 3.若需要判断数组中某元素是否存在,需要使用"index in array"格式进行,不能直接判断数组中的元素是否为空 [root@sakura ~]# awk 'BEGIN{role["riben"]="kasumi";role["china"]="wanglin";print role["riben"]}' kasumi [root@sakura ~]# awk 'BEGIN{role["riben"]="kasumi";role["china"]="wanglin";print role["china"]}' wanglin
2.若需要遍历数组中的每个元素,需要使用for循环
1)for(var in array){for-body}[root@sakura ~]# awk 'BEGIN{role["riben"]="kasumi";role["china"]="wanglin";for(i in role){print role[i]}}' kasumi wanglin [root@sakura ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' Tuesday Monday ps:var会遍历array的每一个索引
2)统计netstat -tan命令中tcp协议各个状态的出现次数
[root@sakura ~]# netstat -tan | awk '/^tcp\>/{stat[$NF]++}END{for(i in stat){print i,stat[i]}}' LISTEN 5 ESTABLISHED 3
3)统计/var/log/httpd/access_log文件中,各个ip访问的次数
[root@sakura ~]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log 192.168.3.19 72
4)统计/etc/fstab文件中每个文件系统类型出现的次数
[root@sakura ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab swap 1 xfs 3
5)统计指定文件中每个单词出现的次数
[root@sakura ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab man 1 May 1 and/or 1 maintained 1 xfs 3 file 1
四.awk内置函数
1.数值处理:rand():返回0和1之间一个随机数
[root@sakura ~]# awk 'BEGIN{print rand()}' 0.237788
2.字符串处理
1)length([s]):返回指定字符串的长度
2)sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容[root@sakura ~]# awk -F: '{print sub(o,O,$1)}' /etc/passwd 1 1 1 ps:显示结果为显示是否替换成功
3)gsubsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容
4)split(s,a,[r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中统计客户端访问http服务的次数 [root@sakura ~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}' 192.168.3.19 3 0.0.0.0 5
ps:awk也可使用自定义函数
-
awk
2011-03-02 13:20:00@roylez: bizarrely trapped详解著名的awk oneliner,第一部分:空行、行号和计算偶然在网上看到有人注释过的《awk oneliner》,而且注释的人声称“全部弄懂这 些就已经是awk高手了”,而我也一直想学下awk又懒得花...cat b_noshp.bat | gawk 'NF {print;print "echo -----",NR,NR,NR;}' > b_noshp_log.bat
详解著名的awk oneliner,第一部分:空行、行号和计算
偶然在网上看到有人注释过的《awk oneliner》,而且注释的人声称“全部弄懂这 些就已经是awk高手了”,而我也一直想学下awk又懒得花时间,然后就觉得这个东 西一定很适合我。为了督促自己看完这个系列,决定整个给翻译一遍。说实话看了 第一篇之后觉得awk的语句也不是那么天书了。原作者是Peteris Krumins,一个很 酷的家伙,你可以在titter上follow他(Peteris Krumins)。
原文请见:http://www.catonmat.net/blog/awk-one-liners-explained-part-one/
将每行后面都添加一个空行
awk '1; { print "" }'
这是怎么意思呢?一个单行awk命令,其实也是一个用awk语言写的程序,每个awk程序,都是由一系列的“匹配模式 { 执行动作 }”语句所组成的。在这个例子里面,有两个语句,“1”和“{print ""}”。在每个“匹配模式——执行动作”语句中,模式和动作都是可以被省略的。如果匹配模式被省略,那么预定的动作将会对输入文件的每一行执行。如果动作被省略,那么就默认会执行
{print }
。所以,这个单行awk语句等同于下面的语句awk '1 {print } {print ""}'
动作只有在匹配模式的值为真的时候才会执行。因为“1”永远为真,所以,这个例子也可以写成下面的形式
awk '{print } {print ""}'
awk中每条
print
语句后都默认会输出一个ORS
变量(Output Record Separator,即输出行分隔符,默认为换行符)。第一个不带参数的print语句,等同于print $0
,其中$0
是代表整行内容的变量。第二个print语句什么也不输出,但是鉴于print语句后都会被自动加上ORS变量,这句的作用就是输出一个新行。于是每行后面加空行的目的就达到了。添加空行的另一种方法
awk 'BEGIN { ORS="/n/n" }; 1'
BEGIN是一个特殊的模式,后面所接的内容,会在文件被读入前执行。这里,对ORS变量进行了重新定义,将一个换行符改成了两个。后面的“1”,同样等价于
{print }
,这样就达到了在每行后用新的ORS添加空行的目的。在每个非空的行后面添加空行
awk 'NF {print $0 "/n"}'
这个语句里面用到了一个新的变量,
NF
(number of fields),即本行被分割成的字段的数目。例如,“this is a test”,会被awk分割成4个词语,NF的值就为4。当遇到空行,分割后的字段数为0,NF为0,后面的匹配动作就不会被执行。这条语句,可以理解成“如果这一行可以分割成任意大于0的部分,那么输出当前行以及一个换行符”。在每行后添加两个空行
awk '1; {print "/n"}'
这一语句与前面的很相似。“1”可以理解为
{print }
,所以整个句子可以改写为awk '{print ; print "/n"}'
它首先输出当前行,然后再输出一个换行符以及一个结束print语句的ORS,也就是另外一个换行符。
为每个文件的内容添加行号
awk '{ print FNR "/t" $0 }'
这个awk程序在每行的内容前添加了一个变量FNR的输出,并用一个制表符进行分隔。FNR(File Number of Row)这个变量记录了当前行在当前文件中的行数。在处理下一个文件时,这个变量会被重置为0。
为所有文件的所有行统一添加行号
awk '{print NR "/t" $0}'
这一句与上一例基本一样,除了使用的行号变量是NR(Number of Row),这个变量不会在处理新文件的时候被重置。所以说,如果你有2个文件,一个10行一个12行,那这个变量会从1一直变到22。
用更漂亮的样式添加行号
awk '{printf("%5d : %s/n", FNR, $0)}'
这个例子用了printf函数来自定义输出样式,它所接受的参数与标准C语言的printf函数基本一致。需要注意的是,printf后不会被自动添加ORS,所以你需要自己指定换行。这个语句指定了行号会右对齐,然后是一个空格和冒号,接着是当前行的内容。
为文件中的非空行添加行号
awk 'NF { $0=++a " :" $0}; {print }'
Awk的变量都是自动定义的:你第一次用到某个变量的时候它就自动被定义了。这个语句在每次遇到一个非空行的时候先把一个变量a加1,然后把a的数值添加到行首,然后输出当前行的内容。
计算文件行数(模拟 wc -l)
awk 'END {print NR}'
END是另外一个不会被检验是否为真的模式,后面的动作会在整个文件被读完后进行。这里是输出最终的行号,即文件的总行数。
对每行求和
awk '{s=0;for (i=0;i<NF;i++) s=s+$i; print s}'
Awk有些类似C语言的语法,比如这里的
for (;;;){ ... }
循环。这句命令会让程序遍历所有NF个字段,并把字段的总和存在变量s中,最后输出s的数值并处理下一行。对所有行所有字段求和
awk '{for (i=0;i<NF;i++) s=s+$i; END {print s+0}'
这个例子与上一个基本一致,除了输出的是所有行所有字段的和。由于变量会被自动定义,s只需要定义一次,故而不需要把s定义成0。另外需要注意的是,它输出
{print s+0}
而非{print s}
,这是因为如果文件为空,s不会被定义就不会有任何输出了,输出s+0可以保证在这种情况下也会输出更有意义的0。将所有字段替换为其绝对值
awk '{ for (i = 1; i <= NF; i++) if ($i < 0) $i = -$i; print }'
这条语句用了C语言的另外两个特性,一个是
if (...) {...}
结构,另外就是省略了大括号。它检查对每一行,检查每个字段的值是否小于0,如果值小于0,则将其改为正数。字段名可以间接地用变量的形式引用,如i=5;$i='hello'
会将第5个字段的内容置为hello。下面的是将这条语句完整的写出来的形式。print语句会在行中所有字段被改为正数后执行。
awk '{ for (i = 1; i <= NF; i++) { if ($i < 0) { $i = -$i; } } print }'
计算文件中的总字段(单词)数
awk '{total=total+NF};END {print total+0}'
这个命令匹配所有的行,并不断的把行中的字段数累加到变量total。执行完成上述动作后,输出total的数值。
输出含有单词Beth的行的数目
awk '/Beth/ {n++}; END {print n+0}'
这个例子含有两个语句。第一句找出匹配/Beth/的行,并对变量n进行累加。在/.../之间的内容为正则表达式,/Beth/匹配所有含有“Beth”的单词(它不仅匹配Beth,同样也匹配Bethe)。第二句在文件处理完成后输出n的数值。这里用n+0是为了让n为0 的情况下输出0而不是一个空行。
寻找第一个字段为数字且最大的行
awk '$1 > max { max=$1; maxline=$0 }; END { print max, maxline }'
这个例子用变量max记录第一个字段的最大值,并把第一个字段最大的行的内容存在变量maxline中。在循环终止后,输出max和maxline的内容。注意:如果在数字都为负数的情况下,这个例子就不能用了,下面的是修改过的版本
awk 'NR == 1 { max = $1; maxline = $0; next; } $1 > max { max=$1; maxline=$0 }; END { print max, maxline }'
在每一行前添加输出该行的字段数
awk '{print NF ":" $0}'
这个例子仅仅是在逐行输出字段数NF,一个冒号,以及该行的内容。
输出每行的最后一个字段
awk '{print $NF}'
awk里面的字段可以用变量的形式引用。这一句输出第NF个字段的内容,而NF就是该行的字段数。
打印最后一行的最后一个字段
awk '{ field = $NF };END {print field}'
这个例子用field记录最后一个字段的内容,并在循环后输出field的内容。
这里是一个更好的版本。它更常用、更简洁也更高效:
awk 'END {print $NF}'
输出所有字段数大于4的行
awk 'NF > 4'
这个例子省略了要执行的动作。如前所述,省略动作等价于
{print}
。输出所有最后一个字段大于4的行
awk '$NF > 4'
这个例子用$NF引用最后一个字段,如果它的数值大于4,那么就输出。
-
用numpy操作矩阵,上三角,下三角矩阵,对角化矩阵
-
校园小情书微信小程序后台代码,这是一个情书小联盟-源码
-
微信SDK的golang实现,短小精悍,同时兼容【企业号/服务号/订阅号/小程序】-源码
-
一个基于微信的接龙小程序,开箱即用-源码
-
三维地图GIS大数据可视化
-
31 kW窄线宽线偏振纳秒全光纤激光器
-
【leetcode-python】1047. 删除字符串中的所有相邻重复项
-
相干多普勒激光雷达风场反演方法研究与实验印证
-
全网唯一的为GIS+BIM而生的cesiumjs或cesium视频教程
-
一个自适应的微信小程序自定义导航栏组件-源码
-
SubstancePainter插件开发-基础入门
-
tuple容器
-
POI微信小程序-源码
-
原生微信小程序电商项目-源码
-
java字符串数组转list实体集合
-
flutter插件调用APP页面、使用原生aar,framework库
-
多线程与线程池技术详解(图书配套)
-
微信小程序自定义组件开发-源码
-
光束夹角及空间分布对光克尔开关门成像的影响
-
Java web-html