awk-F的shellawkprintt问题

awk用法总结命令行操作_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
享专业文档下载特权
&赠共享文档下载特权
&10W篇文档免费专享
&每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
awk用法总结命令行操作
&&awk用法总结命令行操作
你可能喜欢记录学习心得 好记性不如烂笔头
awk取最后一列
想查到某个目录下所有以sd_sensor_xxxx.log等文件中,最后一个序号文件的序号。
也就是,要把xxxx取出来。
解决办法:
1. 首先要取到所有sd_sensor_xxxx.log文件中的最后一行文件,该文件代表了最大的序号;
ls -l sd_*.log | sed -n '$p'当前目录有如下文件:
[root@Real6410 sdcard]# ls
sd_sensor_0000.log
sd_sensor_0002.log
使用命令之后:
[root@Real6410 sdcard]# ls -l sd*.log | sed -n '$p'
-rwxrwxrwx
6 01:29 sd_sensor_0002.log
2. 使用awk取到上述显示内容的最后一列,不需要具体数sd_sensor_0002.log排在第几列。命令:
[root@Real6410 sdcard]# ls -l sd*.log | sed -n '$p'| awk '{print $NF}'
sd_sensor_0002.log
3. 再次使用awk加切分符号将0002分离出来。命令:
ls -l sd*.log | sed -n '$p'| awk '{print $NF}' | awk -F '.' '{print $1}' | awk -F '_' '{print $NF}'使用命令结果:
[root@Real6410 sdcard]# ls -l sd*.log | sed -n '$p'| awk '{print $NF}' | awk -F '.' '{print $1}' | awk -F '_' '{print $NF}'
问题解决。
linux之awk命令获取最后一列
AWK如何打印从某一列到最后一列的内容
awk获取最后一列
awk之提取含有相同段行的第一行和最后一行
使用awk求指定列的最大值最小值
awk:打印某列以后的所有列
Linux -输出文本中的最后一列内容
awk如何取出它的每一行和某一列的某个元素
awk按照某个字段排列,求某个列的最大值最小值
使用awk命令获取文本的某一行,某一列
没有更多推荐了,Shell脚本之awk详解 - 简书
Shell脚本之awk详解
一.基本介绍1.awk:awk是一个强大的文本分析工具,在对文本文件的处理以及生成报表,awk是无可替代的。awk认为文本文件都是结构化的,它将每一个输入行定义为一个记录,行中的每个字符串定义为一个域(段),域和域之间使用分割符分割。2.功能:流控制、数学运算、进程控制、内置的变量和函数、循环和判断3.工作原理:awk 会把每行进行一个拆分,用相应的命令对拆分出来的“段”进行处理。(1)行工作模式,读入文件的每一行,会把一行的内容,存到$0里(2)使用内置的变量FS(段的分隔符,默认用的是空白字符),分割这一行,把分割出来的每个段存到相应的变量$(1-100)(3)输出的时候按照内置变量OFS(out FS),输出(4)读入下一行继续操作简单实例[root@tx3 ~]# echo "this is a book" & awk.txt[root@tx3 ~]# awk '{print $2,$1,$3,$4}' awk.txtis this a book4.
Awk常用内置变量表:1 $0
当前记录(作为单个变量)2 $1~$n
当前记录的第n个字段,字段间由FS分隔3 FS
输入字段分隔符 默认是空格4 NF
当前记录中的字段个数,就是有多少列5 NR
已经读出的记录数,就是行号,从1开始6 RS
输入的记录他隔符默 认为换行符7 OFS
输出字段分隔符 默认也是空格8 ORS
输出的记录分隔符,默认为换行符9 ARGC
命令行参数个数10 ARGV
命令行参数数组11 FILENAME
当前输入文件的名字12 IGNORECASE
如果为真,则进行忽略大小写的匹配13 ARGIND
当前被处理文件的ARGV标志符14 CONVFMT
数字转换格式 %.6g15 ENVIRON
UNIX环境变量16 ERRNO
UNIX系统错误消息17 FIELDWIDTHS
输入字段宽度的空白分隔字符串18 FNR
当前记录数19 OFMT
数字的输出格式 %.6g20 RSTART
被匹配函数匹配的字符串首21 RLENGTH
被匹配函数匹配的字符串长度二.print的简单使用例:打印整行: $0[root@tx3 ~]# cp /etc/passwd p1[root@tx3 ~]# awk '{print $0}' p1例:打印每行的最后一个字段: $NF[root@tx3 ~]# awk -F : '{print $NF}' p1例:打印第三个字段: $3[root@tx3 ~]# awk -F : '{print $3}' p1例:打印第一行NR==1[root@tx3 ~]# awk 'NR==1{print $0}' p1root:x:0:0:root:/root:/bin/bash例:打印最后一行[root@tx3 ~]# awk 'END{print $0}' p1tx:x:500:500:tx:/home/tx:/bin/bash例:打印第一行最后一个字段[root@tx3 ~]# awk -F: 'NR==1{print $NF}' p1/bin/bash例:打印最后一行最后一个字段[root@tx3 ~]#awk -F: 'END{print $NF}' p1例:打印每行的倒数第二个字段,并在其后打印你好[root@tx3 ~]# awk -F: '{print $(NF-1),"nihao"}' p1/root nihao/bin nihao/sbin nihao例:打印行号[root@tx3 ~]# awk '{print NR,$0}' p11 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologin3 daemon:x:2:2:daemon:/sbin:/sbin/nologin例:打印当前系统环境变量的某个特定值[root@tx3 ~]# awk 'BEGIN{print ENVIRON["PATH"];}'/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin例: 用:分割,删除第2个字段[root@tx3 ~]# awk 'BEGIN{FS=":";OFS=":"}{print $1,$3,$4,$5,$6,$7}' p1root:0:0:root:/root:/bin/bashbin:1:1:bin:/bin:/sbin/nologindaemon:2:2:daemon:/sbin:/sbin/nologin三.printf的使用print format 生成报表%d
十进制有符号整数%u
十进制无符号整数%f
显示字符的ASCII码%p
指针的值%e
科学技术法显示数值%x
%X 无符号以十六进制表示的整数%o
无符号以八进制表示的整数%g
%G 以科学计数法或浮点数的格式显示数值%%
显示其自身修饰符:-:
显示数值符号N: 显示-F 指定段的分隔符例:(1)生成报表例:(2)小数问题对小数取保留位的时候,四舍五入对小数取整,不进行四舍五入[root@tx3 ~]# cat awk.123. 45.67[root@tx3 ~]# awk '{printf "%.2f\t%.2f\t%.2f\n",$1,$2,$3}' awk.123.四.awk的使用(1)正则表达式\(\)
\{\} 不支持. * ^ $ ? + [] | \& \& ()
可以直接使用例[root@tx3 ~]# awk '/^$/{print "this is an empty line"}' /etc/inittabthis is an empty linethis is an empty linethis is an empty linethis is an empty linethis is an empty linethis is an empty linethis is an empty linethis is an empty linethis is an empty line例[root@tx3 ~]# awk -F: '/^root/{print $1,$NF}' /etc/passwdroot /bin/bash例[root@tx3 ~]# awk -F: '!/^root/{print $1,$NF}' /etc/passwd|head -3bin /sbin/nologindaemon /sbin/nologinadm /sbin/nologin(2)关系运算符& & == != &= &=~(匹配) !~(不匹配)例[root@tx3 ~]# cp /etc/passwd p1[root@tx3 ~]# awk -F: '$3 == 0 {print $1}' p1Root例[root@tx3 ~]# awk -F: '$3 != 0{ print $1}' p1 | head -2binDaemon例[root@tx3 ~]# awk -F: '$3 & 2 {print $1}' p1rootbin(3)逻辑运算符&& || !与 或 非例[root@tx3 ~]# awk -F: '$3 & 0 && $3 & 10 {print $1, $3}' p1 |head -2bin 1daemon 2例[root@tx3 ~]#
awk -F: '$3 & 10 || $3 & 5 {print $1,$3}' p1 |head -6root 0bin 1daemon 2adm 3lp 4operator 11(4)算数运算符+ - * / %(取模(余数)) ^(幂运算)例:输出名字,总成绩,平均成绩[root@tx3 ~]# cat cjtx 90 86 86tx1 89 78 85tx2 79 80 85[root@tx3 ~]#
awk '{print $1,$2+$3+$4,($2+$3+$4)/3}' cjtx 262 87.3333tx1 252 84tx2 244 81.3333[root@tx3 ~]# awk '{printf"%-5s %3d %.2f\n",$1,$2+$3+$4,($2+$3+$4)/3}' cjtx
262 87.33tx1
252 84.00tx2
244 81.33(5)BEGIN
ENDBEGIN{ 动作;动作;... }
在处理文件之前,要执行的动作;只执行一次END{ 动作;动作;... }
在处理完文件之后,要执行的动作;只执行一次BEGIN :可以给文件添加标题、定义变量、定义文件的分隔符END:汇总的操作getline可以从管道和标准输入读取输入,然后传递给变量。例:[root@tx3 ~]# awk 'BEGIN{"date"| getline a}{print}END{print a}' cjtx 90 86 86tx1 89 78 85tx2 79 80 85Thu Feb
7 12:39:25 CST 2013五.awk里的流控制和循环(1)简单的条件判断语法:(表达式 ? 值1 : 值2) 如果表达式成立,输出值1;否则输出值2[root@tx3 ~]# cat num2 8 98 4 63 5 7[root@tx3 ~]# awk '{print ( $1 & $2 ? $1 : $2)}' num885(2)if判断语法:{ if (表达式{动作1;动作2;...}}如果表达式成立,那么执行动作。[root@tx3 ~]# awk '{if ($2&=80 && $2 &=100) {print $1,"great"} else {print $1, "good"}}' cjtx greattx1 greattx2 good(2)多支判断{if (表达式){ 动作1;动作2;...}else if (表达式){ 动作1;动作2;...}else if (表达式){ 动作1;动作2;...}......else{ 动作1;动作2;...}}[root@tx3 ~]# cat cjtx 90 86 86tx1 89 78 85tx2 79 80 85tx3 80 70 60tx4 75 85 65tx5 78 62 80判断的标准:90-100 A80-89
E[root@tx3 ~]# awk '{ if ($2 &= 90 && $2 &= 100) {print $1,"A"} else if ($2 &= 80 && $2 & 90) {print $1,"B"} else if ($2 &= 70 && $2 & 80) {print $1,"C"} else if ($2 &= 60 && $2 & 70) {print $1,"D"} else {print $1,"E"} }' cjtx Atx1 Btx2 Ctx3 Btx4 Ctx5 C(3)循环while语法:'var=初值;while (表达式){动作1;...更新变量的动作;}'例:[root@tx3 ~]# awk -F: '{i=1; while (i&=NF) {print $i;i++}}' p1 | head -7rootx00root/root/bin/bash例. 方法一[root@tx3 ~]# awk -F: '{i=NF; while (i&=2) {printf $i ":";i--};print $1}' p1/bin/bash:/root:root:0:0:x:root/sbin/nologin:/bin:bin:1:1:x:bin/sbin/nologin:/sbin:daemon:2:2:x:daemon/sbin/nologin:/var/adm:adm:4:3:x:adm例. 方法二[root@tx3 ~]# awk 'BEGIN { FS=":" } { i=NF; while (i&=2) {printf $i ":";i--} print $1}' p1/bin/bash:/root:root:0:0:x:root/sbin/nologin:/bin:bin:1:1:x:bin/sbin/nologin:/sbin:daemon:2:2:x:daemon(4)for循环语法:{for(表达式){动作1;...}}表达式:分为3部分:(1)初始化表达式 i=1(2)测试表达式
i&10(3)更新测试表达式 i++语句:next 处理输入行的下一个输入行exit 退出continue 结束本次循环break 跳出循环例[root@tx3 ~]# awk 'BEGIN {FS=":"} {for(i=NF;i&=2;i--) {printf $i ";"};print $1}' p1/bin//0;0;x;root/sbin//1;1;x;bin/sbin//2;2;x;daemon/sbin//var/4;3;x;adm例[root@tx3 ~]# cat num2 8 98 4 63 5 7[root@tx3 ~]# awk '{ max=0; i=1; while (i&=NF) { if (max&$i) {max=$i} i++} print max}' num987(5)awk数组例
使用变量作为数组下标
另外一种读取方式(这种是无序的,j是变量,a是数组)
(6)函数@1split 切割字符串split("等待被切割的字符串",数组名,"切割用的分隔符")[root@tx3 ~]# awk 'BEGIN{split("",da,"/");print da[2],da[3],da[1]}'08 23 2012@2toupper() 小写转大写tolower() 大写转小写[root@tx3 ~]# awk '{print toupper($0)}' p1 |head -3ROOT:X:0:0:ROOT:/ROOT:/BIN/BASHBIN:X:1:1:BIN:/BIN:/SBIN/NOLOGINDAEMON:X:2:2:DAEMON:/SBIN:/SBIN/NOLOGIN@3sub()
局部替换gsub() 全局替换sub(/要替换的内容/,"替换成什么内容")gsub(/要替换的内容/,"替换成什么内容")gsub(/要替换的内容/,"替换成什么内容",指定字段如$7)例:[root@tx3 ~]# awk -F: '{sub(/root/,"r00t");print}' p1r00t:x:0:0:root:/root:/bin/bash例:[root@tx3 ~]# awk -F: '{gsub(/root/,"r00t");print}' p1r00t:x:0:0:r00t:/r00t:/bin/bashoperator:x:11:0:operator:/r00t:/sbin/nologin例:[root@tx3 ~]# awk -F[:/] '{gsub(/root/,"r00t",$7);print}' p1root x 0 0 root
bin bashoperator x 11 0 operator
sbin nologin@4.length() 计算字符串的长度[root@tx3 ~]# awk -F: '{print length($1),$1}' p14 root3 bin6 daemon3 adm@5. 数学计算[root@tx3 ~]# awk 'BEGIN{print sin(30)}'-0.988032[root@tx3 ~]# awk 'BEGIN{print cos(60)}'-0.952413[root@tx3 ~]# awk 'BEGIN{print int(22/6)}'3[root@tx3 ~]# awk 'BEGIN{print sqrt(3)}'1.73205
awk命令的基本使用 [root@shellscript ~]# head -n 3 /etc/passwd | tail -n 1 | awk -F: '{print $1}' daemon [root@shellscript ~]# head -n 3 /etc/pas...
awk: grep,sed,awk grep:文本过滤 sed:文本编辑 awk:文本格式化工具; 1 什么是awk、nawk、gawk awk是一种用于处理数据和生成报告的UNIX编程语言。nawk时awk的新版本,gawk是基于Linux的GNU版本。 awk简介: a...
awk的简介和功能 awk: Linux 文本处理三剑客:grep、sed和awk。其中grep是一种文本过滤工具,sed是文本行编辑器,而 awk 是一种报表生成器,就是对文件进行格式化处理的,这里的格式化不是文件系统的格式化,而是对文件内容进行各种“排版”,进而格式化显...
sed工具简介 用法:sed [-nefri]
动作参数:-n:使用安静模式(Silent)模式,一般在sed的 用法中,所有来自STDIN的数据一般都会列在屏幕上。但如果是加上-n参数后,则只有经过sed特殊处理的那一行(或操作)才会被列出来-e:直接在命令行模式上进行...
【MySQL】Linux下MySQL 5.5、5.6和5.7的RPM、二进制和源码安装 1.1BLOG文档结构图 1.2前言部分 1.2.1导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ①MySQ...
我发现在大城市工作的姑娘们有一个通病,大家普遍对回家过年这事儿特别紧张。 这几天,写字楼里的Mary,Catherine,Rebecca都要卸妆,变成翠花,招弟,春喜。她们在这样的落差中,在亲戚朋友的询问中,过年的这几天,只想要赶快过去,甚至落荒而逃。 好像七大姑八大姨比每...
过了今天,简书“新爸五年计划”就要结束了,然后进入下一阶段,记录并履行这个计划书了。 其实,生娃时都没想过要好好计划一下,想不到养娃了却得好好计划一下了。 嗯,计划生育,计划教育,看来是有道理的。 看了很多新爸老爸的计划书,总体觉得都差不多,好像养孩子也就那么会事,当然也有...
分享一组电影原画,太震撼了。 原作者:卡尔·林德伯格 《金刚:骷髅岛》是由华纳兄弟影片公司、传奇影业、上海腾讯影业文化传播有限公司联合出品的奇幻冒险片 ,由乔丹·沃格-罗伯茨执导,汤姆·希德勒斯顿、布丽·拉尔森、塞缪尔·杰克逊、约翰·古德曼、景甜、约翰·C·赖利领衔主演。影...
一直想有个平台,可以随意的写一写自己的所思所想,日常感悟。
其实,之前一直想自己写一部小说。记得高中的时候还对室友说过,等我大学有时间写小说了,你们一定要捧场。但是等到大学后,又为自己找借口,自己的阅历不够,构建不出那么大的小说框架,曾经一时冲动买了笔记本电脑,理由是我...
上班族,工作累了或压力大了,总会想着,大不了老子不干了~你看那自由职业者多好,自由自在,无拘无束,活的端是一个潇洒!其实,若真正离职,体会到自由职业时,才会发现远非表面看起来那么光鲜。
人们都说自由职业者时间自由、地点自由、不用看老板颜色,实际上收入不稳,社交...一. AWK入门指南
Awk是一种便于使用且表达能力强的程序设计语言,可应用于各种计算和数据处理任务。本章是个入门指南,让你能够尽快地开始编写你自己的程序。第二章将描述整个语言,而剩下的章节将向你展示如何使用Awk来解决许多不同方面的问题。纵观全书,我们尽量选择了一些对你有用、有趣并且有指导意义的实例。
有用的awk程序往往很简短,仅仅一两行。假设你有一个名为 emp.data 的文件,其中包含员工的姓名、薪资(美元/小时)以及小时数,一个员工一行数据,如下所示:
现在你想打印出工作时间超过零小时的员工的姓名和工资(薪资乘以时间)。这种任务对于awk来说就是小菜一碟。输入这个命令行就可以了::
awk '$3 &0 { print $1, $2 * $3 }' emp.data
你应该会得到如下输出:
Susie 76.5
该命令行告诉系统执行引号内的awk程序,从输入文件 emp.data 获取程序所需的数据。引号内的部分是个完整的awk程序,包含单个模式-动作语句。模式 $3&0 用于匹配第三列大于0的输入行,动作:
{ print $1, $2 * $3 }
打印每个匹配行的第一个字段以及第二第三字段的乘积。
如果你想打印出还没工作过的员工的姓名,则输入命令行::
awk '$3 == 0 { print $1 }' emp.data
这里,模式 $3 == 0 匹配第三个字段等于0的行,动作:
{ print $1 }
打印该行的第一个字段。
当你阅读本书时,应该尝试执行与修改示例程序。大多数程序都很简短,所以你能快速理解awk是如何工作的。在Unix系统上,以上两个事务在终端里看起来是这样的:
$ awk ‘$3 & 0 { print $1, $2 * $3 }’ emp.data
Susie 76.5
$ awk ‘$3 == 0 { print $1 }’ emp.data
行首的 $ 是系统提示符,也许在你的机器上不一样。
AWK程序的结构
让我们回头看一下到底发生了什么事情。上述的命令行中,引号之间的部分是awk编程语言写就的程序。本章中的每个awk程序都是一个或多个模式-动作语句的序列:
{ action }
{ action }
awk的基本操作是一行一行地扫描输入,搜索匹配任意程序中模式的行。词语“匹配”的准确意义是视具体的模式而言,对于模式 $3 &0 来说,意思是“条件为真”。
每个模式依次测试每个输入行。对于匹配到行的模式,其对应的动作(也许包含多步)得到执行,然后读取下一行并继续匹配,直到所有的输入读取完毕。
上面的程序都是模式与动作的典型示例。:
$3 == 0 { print $1 }
是单个模式-动作语句;对于第三个字段为0的每行,打印其第一个字段。
模式-动作语句中的模式或动作(但不是同时两者)都可以省略。如果某个模式没有动作,例如::
那么模式匹配到的每一行(即,对于该行,条件为真)都会被打印出来。该程序会打印 emp.data 文件中第三个字段为0的两行
如果有个没有模式的动作,例如::
{ print $1 }
那么这种情况下的动作会打印每个输入行的第一列。
由于模式和动作两者任一都是可选的,所以需要使用大括号包围动作以区分于其他模式。
执行AWK程序
执行awk程序的方式有多种。你可以输入如下形式的命令行::
awk 'program' input files
从而在每个指定的输入文件上执行这个program。例如,你可以输入::
awk '$3 == 0 { print $1 }' file1 file2
打印file1和file2文件中第三个字段为0的每一行的第一个字段。
你可以省略命令行中的输入文件,仅输入::
awk 'program'
这种情况下,awk会将program应用于你在终端中接着输入的任意数据行,直到你输入一个文件结束信号(Unix系统上为control-d)。如下是Unix系统的一个会话示例:
$ awk ‘$3 == 0 { print $1 }’
Kathy 3.75
Kathy 3.75
加粗的字符是计算机打印的。
这个动作非常便于尝试awk:输入你的程序,然后输入数据,观察发生了什么。我们再次鼓励你尝试这些示例并进行改动。
注意命令行中的程序是用单引号包围着的。这会防止shell解释程序中 $ 这样的字符,也允许程序的长度超过一行。
当程序比较短小(几行的长度)的时候,这种约定会很方便。然而,如果程序较长,将程序写到一个单独的文件中会更加方便。假设存在程序 progfile ,输入命令行::
awk -f progfile
optional list of input files
其中 -f 选项指示awk从指定文件中获取程序。可以使用任意文件名替换 progfile 。
如果你的awk程序存在错误,awk会给你一段诊断信息。例如,如果你打错了大括号,如下所示::
awk '$3 == 0 [ print $1 }' emp.data
你会得到如下信息:
awk: syntax error at source line 1
context is
$3 == 0 &&& [ &&&
awk: bailing out at source line 1
“Syntax error”意味着在 &&& &&& 标记的地方检测到语法错误。“Bailing out”意味着没有试图恢复。有时你会得到更多的帮助-关于错误是什么,比如大括号或括弧不匹配。
因为存在句法错误,awk就不会尝试执行这个程序。然而,有些错误,直到你的程序被执行才会检测出来。例如,如果你试图用零去除某个数,awk会在这个除法的地方停止处理并报告输入行的行号以及在程序中的行号(这话是什么意思?难道输入行的行号是忽略空行后的行号?)。
1.2 简单输出
这一节接下来的部分包含了一些短小,典型的awk程序,基于操纵上文中提到的
emp.data 文件. 我们会简单的解释程序在做什么,但这些例子主要是为了介绍
awk 中常见的一些简单有用的操作 – 打印字段, 选择输入, 转换数据. 我们并
没有展现 awk 程序能做的所有事情, 也并不打算深入的去探讨例子中的一些细节.
但在你读完这一节之后, 你将能够完成一些简单的任务, 并且你将发现在阅读后
面章节的时候会变的容易的多.
我们通常只会列出程序部分, 而不是整个命令行. 在任何情况下, 程序都可以用
引号包含起来放到 awk 命令的地一个参数中运行, 就像上文中展示的那样, 或者
把它放到一个文件中使用 awk 的 -f 参数调用它.
在 awk 中仅仅只有两种数据类型: 数值 和 字符构成的字符串. emp.data 是
一个包含这类信息的典型文件 – 混合了被空格和(或)制表符分割的数字和词语.
Awk 程序一次从输入文件的中读取一行内容并把它分割成一个个字段, 通常默认
情况下, 一个字段是一个不包含任何空格或制表符的连续字符序列. 当前输入的
行中的地一个字段被称做 $1, 第二个是 $2, 以此类推. 整个行的内容被定
义为 $0. 每一行的字段数量可以不同.
通常, 我们要做的仅仅只是打印出每一行中的某些字段, 也许还要做一些计算.
这一节的程序基本上都是这种形式.
打印每一行
如果一个动作没有任何模式, 这个动作会对所有输入的行进行操作. print 语
句用来打印(输出)当前输入的行, 所以程序
会输出所有输入的内容到标准输出. 由于 $0 表示整行,
{ print $0 }
也会做一样的事情.
打印特定字段
使用一个 print 语句可以在同一行中输出不止一个字段. 下面的程序输出了每
行输入中的第一和第三个字段
{ print $1, $3 }
使用 emp.data 作为输入, 它将会得到
在 print 语句中被逗号分割的表达式, 在默认情况下他们将会用一个空格分割
来输出. 每一行 print 生成的内容都会以一个换行符作为结束. 但这些默认行
为都可以自定义; 我们将在第二章中介绍具体的方法.
NF, 字段数量
很显然你可能会发现你总是需要通过 $1, $2 这样来指定不同的字段, 但任何表
达式都可以使用在$之后来表达一个字段的序号; 表达式会被求值并用于表示字段
序号. Awk会对当前输入的行有多少个字段进行计数, 并且将当前行的字段数量存
储在一个内建的称作 NF 的变量中. 因此, 下面的程序
{ print NF, $1, $NF }
会依次打印出每一行的字段数量, 第一个字段的值, 最后一个字段的值.
计算和打印
你也可以对字段的值进行计算后再打印出来. 下面的程序
{ print $1, $2 * $3 }
是一个典型的例子. 它会打印出姓名和员工的合计支出(以小时计算):
Susie 76.5
我们马上就会学到怎么让这个输出看起来更漂亮.
Awk提供了另一个内建变量, 叫做 NR, 它会存储当前已经读取了多少行的计数.
我们可以使用 NR 和 $0 给 emp.data 的没一行加上行号:
{ print NR, $0 }
打印的输出看起来会是这样:
在输出中添加内容
你当然也可以在字段中间或者计算的值中间打印输出想要的内容:
{ print &total pay for&, $1, &is&, $2 * $3 }
total pay for Beth is 0
total pay for Dan is 0
total pay for Kathy is 40
total pay for Mark is 100
total pay for Mary is 121
total pay for Susie is 76.5
在打印语句中, 双引号内的文字将会在字段和计算的值中插入输出.
1.3 高级输出
print 语句可用于快速而简单的输出。若要严格按照你所想的格式化输出,则需要使用 printf 语句。正如我将在2.4节所见, printf 几乎可以产生任何形式的输出,但在本节中,我们仅展示其部分功能。
printf 语句的形式如下::
printf(format, value1, value2, ..., valuen)
其中 format 是字符串,包含要逐字打印的文本,穿插着 format 之后的每个值该如何打印的规格(specification)。一个规格是一个 % 符,后面跟着一些字符,用来控制一个 value 的格式。第一个规格说明如何打印 value1 ,第二个说明如何打印 value2 ,... 。因此,有多少 value 要打印,在 format 中就要有多少个 % 规格。
这里有个程序使用 printf 打印每位员工的总薪酬::
{ printf(&total pay for %s is $%.2f\n&, $1, $2 * $3) }
printf 语句中的规格字符串包含两个 % 规格。第一个是 %s ,说明以字符串的方式打印第一个值 $1 。第二个是 %.2f ,说明以数字的方式打印第二个值 $2*$3 ,并保留小数点后面两位。规格字符串中其他东西,包括美元符号,仅逐字打印。字符串尾部的 \n 代表开始新的一行,使得后续输出将从下一行开始。以 emp.data 为输入,该程序产生:
total pay for Beth is $0.00
total pay for Dan is $0.00
total pay for Kathy is $40.00
total pay for Mark is $100.00
total pay for Mary is $121.00
total pay for Susie is $76.50
printf 不会自动产生空格或者新的行,必须是你自己来创建,所以不要忘了 \n 。
另一个程序是打印每位员工的姓名与薪酬::
{ printf(&%-8s $%6.2f\n&, $1, $2 * $3) }
第一个规格 %-8s 将一个姓名以字符串形式在8个字符宽度的字段中左对齐输出。第二个规格 %6.2f 将薪酬以数字的形式,保留小数点后两位,在6个字符宽度的字段中输出。
之后我们将展示更多的 printf 示例。一切精彩尽在2.4小节。
假设你想打印每位员工的所有数据,包括他或她的薪酬,并以薪酬递增的方式进行排序输出。最简单的方式是使用awk将每位员工的总薪酬置于其记录之前,然后利用一个排序程序来处理awk的输出。Unix上,命令行如下:
awk '{ printf(&%6.2f
%s\n&, $2 * $3, $0) }' emp.data | sort
将awk的输出通过管道传给 sort 命令,输出为:
Kathy 4.00 10
Susie 4.25 18
Awk的模式适合用于为进一步的处理从输入中选择相关的数据行。由于不带动作的模式会打印所有匹配模式的行,所以很多awk程序仅包含一个模式。本节将给出一些有用的模式示例。
通过对比选择
这个程序使用一个对比模式来选择每小时赚5美元或更多的员工记录,也就是,第二个字段大于等于5的行::
从 emp.data 中选出这些行::
通过计算选择
$2 * $3 & 50 { printf(&$%.2f for %s\n&, $2 * $3, $1) }
打印出总薪资超过50美元的员工的薪酬。
通过文本内容选择
除了数值测试,你还可以选择包含特定单词或短语的输入行。这个程序会打印所有第一个字段为 Susie 的行::
$1 == &Susie&
操作符 == 用于测试相等性。你也可以使用称为 正则表达式 的模式查找包含任意字母组合,单词或短语的文本。这个程序打印任意位置包含 Susie 的行::
输出为这一行::
正则表达式可用于指定复杂的多的模式;2.1节将会有全面的论述。
可以使用括号和逻辑操作符与 && , 或 || , 以及非 ! 对模式进行组合。程序:
$2 &= 4 || $3 &= 20
会打印 $2 (第二个字段) 大于等于 4 或者 $3 (第三个字段) 大于等于 20 的行::
两个条件都满足的行仅打印一次。与如下包含两个模式程序相比::
如果某个输入行两个条件都满足,这个程序会打印它两遍::
注意如下程序:
!($2 & 4 && $3 & 20)
会打印极不满足 $2 小于4也不满足 $3 小于20的行;这个条件与上面第一个模式组合等价,虽然也许可读性差了点。
实际的数据中总是会存在错误的。在数据验证-检查数据的值是否合理以及格式是否正确-方面,Awk是个优秀的工具。
数据验证本质上是否定的:不是打印具备期望属性的行,而是打印可疑的行。如下程序使用对比模式
将5个数据合理性测试应用于 emp.data 的每一行::
{ print $0, &number of fields is not equal to 3& }
{ print $0, &rate is below minimum wage& }
{ print $0, &rate exceeds $10 per hour& }
{ print $0, &negative hours worked& }
{ print $0, &too many hours worked& }
如果没有错误,则没有输出。
BEGIN与END
特殊模式 BEGIN 用于匹配第一个输入文件的第一行之前的位置, END 则用于匹配处理过的最后一个文件的最后一行之后的位置。这个程序使用 BEGIN 来输出一个标题::
BEGIN { print &Name
HOURS&; print &&}
程序的动作部分你可以在一行上放多个语句,不过要使用分号进行分隔。注意 普通的 print 是打印当前输入行,与之不同的是 print “” 会打印一个空行。
1.5 使用AWK进行计算
一个动作就是一个以新行或者分号分隔的语句序列。你已经见过一些其动作仅是单个 print 语句的例子。本节将提供一些执行简单的数值以及字符串计算的语句示例。在这些语句中,你不仅可以使用像 NF 这样的内置变量,还可以创建自己的变量用于计算、存储数据诸如此类的操作。awk中,用户创建的变量不需要声明。
这个程序使用一个变量 emp 来统计工作超过15个小时的员工的数目::
$3 & 15 { emp = emp + 1 }
{ print emp, &employees worked more than 15 hours& }
对于第三个字段超过15的每行, emp 的前一个值加1。以 emp.data 为输入,该程序产生::
3 employees worked more than 15 hours
用作数字的awk变量的默认初始值为0,所以我们不需要初始化 emp 。
求和与平均值
为计算员工的数目,我们可以使用内置变量 NR ,它保存着到目前位置读取的行数;在所有输入的结尾它的值就是所读的所有行数。
END { print NR, &employees& }
6 employees
如下是一个使用 NR 来计算薪酬均值的程序::
{ pay = pay + $2 * $3 }
END { print NR, &employees&
print &total pay is&, pay
print &average pay is&, pay/NR
第一个动作累计所有员工的总薪酬。 END 动作打印出
6 employees
total pay is 337.5
average pay is 56.25
很明显, printf 可用来产生更简洁的输出。并且该程序也有个潜在的错误:在某种不太可能发生的情况下, NR 等于0,那么程序会试图执行零除,从而产生错误信息。
awk的优势之一是能像大多数语言处理数字一样方便地处理字符串。awk变量可以保存数字也可以保存字符串。这个程序会找出时薪最高的员工::
$2 & maxrate { maxrate = $2; maxemp = $1 }
END { print &highest hourly rate:&, maxrate, &for&, maxemp }
highest hourly rate: 5.50 for Mary
这个程序中,变量 maxrate 保存着一个数值,而变量 maxemp 则是保存着一个字符串。(如果有几个员工都有着相同的最大时薪,该程序则只找出第一个。)
字符串连接
可以合并老字符串来创建新字符串。这种操作称为 连接(concatenation) 。程序
{ names = names $1 & &}
END { print names }
通过将每个姓名和一个空格附加到变量 names 的前一个值, 来将所有员工的姓名收集进单个字符串中。最后 END 动作打印出 names 的值::
Beth Dan Kathy Mark Mary Susie
awk程序中,连接操作的表现形式是将字符串值一个接一个地写出来。对于每个输入行,程序的第一个语句先连接三个字符串: names 的前一个值、当前行的第一个字段以及一个空格,然后将得到的字符串赋值给 names 。因此,读取所有的输入行之后, names 就是个字符串,包含所有员工的姓名,每个姓名后面跟着一个空格。用于保存字符串的变量的默认初始值是空字符串(也就是说该字符串包含零个字符),因此这个程序中的 names 不需要显式初始化。
打印最后一个输入行
虽然在 END 动作中 NR 还保留着它的值,但 $0 没有。程序
{ last = $0 }
END { print last }
是打印最后一个输入行的一种方式::
我们已看到awk提供了内置变量来保存某些频繁使用的数量,比如:字段的数量和输入行的数量。类似地,也有内置函数用来计算其他有用的数值。除了平方根、对数、随机数诸如此类的算术函数,也有操作文本的函数。其中之一是 length ,计算一个字符串中的字符数量。例如,这个程序会计算每个人的姓名的长度::
{ print $1, length($1) }
行、单词以及字符的计数
这个程序使用了 length 、 NF 、以及
NR 来统计输入中行、单词以及字符的数量。为了简便,我们将每个字段看作一个单词。
{ nc = nc + length($0) + 1
nw = nw + NF
END { print NR, &lines,&, nw, &words,&, nc, &characters& }
文件 emp.data 有:
6 lines, 18 words, 77 characters
$0 并不包含每个输入行的末尾的换行符,所以我们要另外加个1。
1.6 控制语句
Awk为选择提供了一个 if-else 语句,以及为循环提供了几个语句,所以都效仿C语言中对应的控制语句。它们仅可以在动作中使用。
if-else语句
如下程序将计算时薪超过6美元的员工的总薪酬与平均薪酬。它使用一个 if 来防范计算平均薪酬时的零除问题。
$2 & 6 { n = n + 1; pay = pay + $2 * $3 }
{ if (n & 0)
print n, &employees, total pay is&, pay,
&average pay is&, pay/n
print &no employees are paid more than $6/hour&
emp.data 的输出是::
no employees are paid more than $6/hour
if-else 语句中,if 后的条件会被计算。如果为真,执行第一个 print 语句。否则,执行第二个 print 语句。注意我们可以使用一个逗号将一个长语句截断为多行来书写。
一个 while 语句有一个条件和一个执行体。条件为真时执行体中的语句会被重复执行。这个程序使用公式 \(value = amount (1 + rate)^{years}\)
来演示以特定的利率投资一定量的钱,其数值是如何随着年数增长的。
# interest1 - 计算复利
输入: 钱数
输出: 复利值
while (i &= $3) {
printf(&\t%.2f\n&, $1 * (1 + $2) ^ i)
条件是 while 后括弧包围的表达式;循环体是条件后大括号包围的两个表达式。 printf 规格字符串中的 \t 代表制表符; ^ 是指数操作符。从 # 开始到行尾的文本是注释,会被awk忽略,但能帮助程序的读者理解程序做的事情。
你可以为这程序输入三个一组的数字,看看不一样的钱数、利率、以及年数会产生什么。例如,如下事务演示了1000美元,利率为6%与12%,5年的复利分别是如何增长的::
$ awk -f interest1
1000 .06 5
1000 .12 5
另一个语句, for ,将大多数循环都包含的初始化、测试、以及自增压缩成一行。如下是之前利息计算的 for 版本::
# interest1 - 计算复利
输入: 钱数
输出: 每年末的复利
{ for (i = 1; i &= $3; i = i + 1)
printf(&\t%.2f\n&, $1 * (1 + $2) ^ i)
初始化 i = 1 只执行一次。接下来,测试条件 i &= $3 ;如果为真,则执行循环体的 printf 语句。循环体执行结束后执行自增 i = i + 1 ,接着由另一次条件测试开始下一个循环迭代。代码更加紧凑,并且由于循环体仅是一条语句,所以不需要大括号来包围它。
awk为存储一组相关的值提供了数组。虽然数组给予了awk很强的能力,但在这里我们仅展示一个简单的例子。如下程序将按行逆序打印输入。第一个动作将输入行存为数组 line 的连续元素;即第一行放在 line[1] ,第二行放在 line[2] , 依次继续。 END 动作使用一个 while 语句从后往前打印数组中的输入行::
# 反转 - 按行逆序打印输入
{ line[NR] = $0 }
# 记下每个输入行
END { i = NR
# 逆序打印
while (i & 0) {
print line[i]
以 emp.data 为输入,输出为
如下是使用 for 语句实现的相同示例::
# 反转 - 按行逆序打印输入
{ line[NR] = $0 }
# 记下每个输入行
END { for (i = NR; i & 0; i = i - 1)
print line[i]

我要回帖

更多关于 awkF 的文章

 

随机推荐