利用 AWK 的数值计算功能提升工作效率(转载)

Awk 是一种优秀的文本样式扫描和处理工具。转文侧重介绍了 awk 在数值计算方面的运用,并通过几个实际工作中的例子,阐述了如何利用 awk 的计算功能来提高我们的工作效率。转文源自IBM Bluemix,链接:http://www.ibm.com/developerworks/cn/linux/l-cn-awkinwork/

Awk 是一种优秀的文本样式扫描和处理工具。 Awk 与 sed 和 grep 有些相似, 但功能比后者强不少。 awk 提供的功能包括样式载入, 流控制,数学运算符,进程控制以及许多内置的变量和函数等。 借助于这些功能, 我们可以很方便地利用 awk 对各种文件 (如试验产生的数据文件,数据库文件等) 进行处理。 本文介绍了 awk 在数值计算方面的运用, 并通过几个实际的例子, 阐述了如何利用 awk 的计算功能来提高我们的工作效率。

Awk 基本的运算符,数学函数以及简单的运算实例

Awk 支持不少常见的运算符, 如 + (加),- (减), * (乘), / (除), ^ 或 ** (乘方), % (取模) 等等。 此外, awk 也提供了一些常用的数学函数, 比如 sin(x)cos(x)exp(x)log(x)sqrt(x),rand()。 使用这些运算符和函数可以直接进行一些简单的运算:

清单 1. 用 awk 做简单的数值计算
echo | awk ‘{print 19+7}‘ ==> 26
echo | awk ‘{print 19-7}‘ ==> 12
echo | awk ‘{print 19*7}‘ ==> 133
echo | awk ‘{print 19/7}‘ ==> 2.71429
echo | awk ‘{print 19**7}‘ ==> 893871739
echo | awk ‘{print 19%7}‘ ==> 5
echo | awk ‘{print atan2(19, 7)}‘ ==> 1.21781

上面的计算也可以用一个脚本文件 calc.awk 来完成:

清单 2. 脚本文件 calc.awk
{
  print $1 " + " $2 " = " $1 + $2
  print $1 " - " $2 " = " $1 - $2
  print $1 " x " $2 " = " $1 * $2
  print $1 " / " $2 " = " $1 / $2
  print $1 " ^ " $2 " = " $1 ** $2
  print $1 " mod " $2 " = " $1 % $2
  print " atan2( " $1 " , " $2 " ) " " = " atan2($1, $2)
}

执行 awk -f calc.awk 19 7 可以得到和清单 1 中一样的计算结果。 这里选项 -f 允许 awk 调用并执行程序文件 calc.awk; 最后的 19 和 7 是输入, 分别对应于文件中的 $1 和 $2

复杂一些的数值计算

现在我们利用 awk 来完成一些稍微复杂的计算。 我们首先用 awk 来计算 Fibonacci 数列,相应的 awk 程序 Fib.awk 见清单3:

清单 3. 计算 Fibonacci 数列的程序文件
function fibo(n) {
  if(n<=1) return 1;
  return (fibo(n-2) + fibo(n-1));
 }
 BEGIN {
   n = (ARGV[1] < 1) ? 1 : ARGV[1];
   printf("%d\n", fibo(n));
   exit;
 }

计算时使用命令 awk -f Fib.awk n。 这里的输入 n 是整数。 另外只要把上面程序中的函数fibo(n) 稍微改一下, 就可以用来进行阶乘的运算, 修改后的代码如下:

清单 4. 计算价乘的 awk 脚本
function factorial(n) {
  if(n<=1) return 1;
  return (n*factorial(n-1));
 }
BEGIN {
   n = (ARGV[1] < 1) ? 1 : ARGV[1];
   printf("%d\n", factorial(n));
   exit;
 }

我们再来看一个求平方根的例子。 尽管 awk 提供了计算平方根的函数, 但我们也可以通过自己写程序来实现, 相应的算法如清单 5 所示; 清单 6 则给出了一个具体的例子: 求数字 3.7 的平方根:

清单 5. 求平方根的算法

清单 6. 计算平方根的例子
BEGIN {
   a = 3.7;
  x = a; 

while((x**2-a)**2 > 1e-12) {
 x = (x + a/x)/2;
}

   print x
 }

实例1: 快速计算两个文件之间的时间差

如果仅仅从事单纯的数值计算, 恐怕 awk 不是我们最好的选择, 毕竟 awk 是为了方便文本处理而设计的。 不过如果数值计算和文本有密切关系的话, 比方说计算之前要先处理文本中的数据 (如查找,提取数据), 这时 awk 的优势就会充分显示出来。 而这样的情况在工作中往往是经常碰到的。 我们来看一个实际的例子。 假定我们要比较某些运行在 Linux 集群上的并行程序的效率, 一个可行的方法是估算这些程序运行所需的时间。 这些程序运行的时间通常比较长, 可以从 10 几个小时到一个多星期。 注意到程序在运行中会不断地生成数据文件, 而 Linux 系统会纪录下每个数据文件被创建 (如果以前不存在) 或修改(如果以前存在) 的时间, 这样就可以通过计算两个文件的时间差来估计并行程序的效率。 我们知道 Linux 提供的 stat 命令可以用来获取某个文件的各种属性, 比如对数据文件 simu_space_1.dat 使用命令 stat simu_space_1.dat 会有如下的输出:

清单 7. 命令 stat simu_space_1.dat 的输出
File:  "simu_space_1.dat"
 Size: 237928    	Blocks: 480        IO Block: 4096   regular Datei
Device: 801h/2049d	Inode: 2768915     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     nst)   Gid: ( 1000/     nst)
Access: 2008-11-14 10:56:05.000000000 +0100
Modify: 2008-11-13 23:26:44.000000000 +0100
Change: 2008-11-13 23:26:44.000000000 +0100

以上输出包含了关键字 ’Modify’ 的一行中纪录下了文件被修改的时间。 所以原则上说只要对两个文件分别使用 stat 命令, 得到它们的修改时间, 就可以计算出它们之间的时间差。 如果计算的次数很少的话, 这个工作当然可以手工完成。 不过要频繁计算的话就很费时间了, 而且出错的几率也会变大。 这种情况下我们可以求助 awk, 让它来自动完成这个计算工作, 为此我们创建了下面的脚本 time_df.awk:

清单 8. 计算时间差的 awk 程序
BEGIN {
  n = 0;
  d1 = 0;
  s1 = 0;
  FS = ":|-| *";
}

{
 for(i=1; i<=NF; i++)
 {
   if($i~/Modify/)
   {
    n = n + 1;
    d = $(i+4);
    h = $(i+5);
    m = $(i+6);
    s = $(i+7);
    d1 = d1 + ((-1)**n)*d*24*3600;
    s1 = s1 + ((-1)**n)*(3600*h + 60*m + s);
   }
 }
}

END {
  s1 = s1 + d1;
  D = int(s1/(24*3600));
  H = int((s1 - D*24*3600)/3600);
  M = int((s1-D*24*3600-H*3600)/60);
  S = s1 % 60;
  printf("The total time required %d days, %d hours,     %d minutes and %d seconds\n", D, H, M, S) ;
}

上面的代码是基于如下的考虑: 首先使用 awk 找到包含 ’Modify’ 关键字的那一行, 然后把其中有关日期和时间的数据提取出来。 由于直接对日期和时间做减法不是很方便, 所以先把日期和时间转化为一个以秒为单位的数字 (从每个月的第一天0时0分0秒算起)。 容易理解, 由两个数字相减得到的时间差也是以秒为单位的。 为了能直观显示, 输出时再把这个时间差表达为天, 小时, 分钟和秒。 要计算两个文件 simu_space_1.dat 和 simu_space_100.dat 之间的时间差,可以用下面的命令:

清单 9. 计算文件时间差的命令
stat simu_space_1.dat simu_space_100.dat | awk -f time_df.awk

先生成的文件 simu_space_1.dat (也就是时间较早一些的) 放在前面,后生成的文件simu_space_100.dat 放在后面。 如果要算另外两个文件之间的时间差, 只要换一下文件名就可以了。 借助于上面的 awk 代码我们可以快速且精确地得到任意两个数据文件的时间间隔。 需要指出的是, 上面的程序没有考虑跨月度这种情况。 也就是说, 如果第一个数据文件是在某个月的月末生成, 而第二个文件是在下个月的月初生成, 这时就不能用它来计算, 因为得到的时间是没有意义的负数。

实例2: 验证通量:从多个文件中提取数据并计算

这个例子是通过计算不同位置处的流体的通量来验证它们是否相同。 这里的通量可视为某个截面上通过的颗粒浓度, 流体的速度和截面面积的乘积。 现在的问题是浓度, 速度等参数分布在不同的数据文件中, 而这些文件是字符和数据共存的, 比如包含浓度的文件 simu_space_1.dat 有如下的格式:

清单 10. 数据文件 simu_space_1.dat 的格式

{0.436737, 0.429223, 3.000000, 1.000000, 43300806482080792.000000, 243231808.137785},

{1.296425, 0.429223, 3.000000, 1.000000, 107468809895964656.000000, 584622938.047805},

{2.128973, 0.429223, 3.000000, 1.000000, 102324821165926400.000000, 539067822.351442},

......

{19.358569, 4.875000, 3.000000, 1.000000, 257544788738191712.000000, 1460324590.999991},

{19.620925, 4.875000, 3.000000, 1.000000, 266676357086157504.000000, 1464352706.940682},

{19.875000, 4.875000, 3.000000, 1.000000, 260249342336872224.000000, 1383971975.659338},

第一步当然是从上面的文件中把某个位置上的浓度数据 (每一行左起第五个数字) 提取出来。 下面的 awk 代码是把位置 x = 0.429223 处的浓度提取出来, 并保存到一个临时文件 number.txt 中:

清单 11. 提取指定位置处的数据并保存
awk  -F‘{|,\t|},‘ ‘{for(i=1; i<NF; i++) {if($i~/0.429223/) print $(i+3)}}‘  simu_space_1.dat > number.txt

现在文件 number.txt 中有了一列浓度数据。 接着我们从其他文件中提取在同一位置处的速度和面积的数据, 然后把它们分别保存到临时文件 velocity.txt 和 area.txt 中。 然后把三个临时文件中的数据合并到另一个文件 flux.txt 中以方便 awk 的计算。 这个合并操作可以用工具 paste 来轻松完成, 代码如清单 12:

清单 12. 合并不同文件中的数据到一个文件
paste number.txt velocity.txt area.txt > flux.txt

现在 flux.txt 中包含了三列数据, 分别是浓度,速度和面积。 按照前面介绍的通量计算方法, 文件 flux.txt 中每一行的三个数据要首先相乘, 然后再把所有的乘积加起来就可以得到通过那个截面的通量了, 具体的代码见清单13:

清单 13. 计算通量的 awk 代码
awk ‘{x=x+($1*$2*$3)} END {print x}‘ flux.txt

上面的代码使用了一个变量 x, 第一次执行时, x 被赋予文件 flux.txt 中第一行三个数据的乘积。 第二次执行时, 它保留了第一次计算的值并加上第二行三个数据的乘积, 以此类推, 直到达到累计的总合。 END 的作用是只显示最后的结果, 而不显示中间的累加结果。 我们可以做一个比较, 以前我们是利用其他的软件 (比如 Excel 或者 OpenOffice Calc) 来计算通量的。 这必然要涉及到导入数据, 选择相应的计算函数等一系列的操作, 而用 awk 只要一行代码! 如果再考虑到计算之前从不同文件中提取数据的工作也是由 awk 完成的 (其实也就是几行代码), 所以对本例而言使用 awk 节约了可观的时间。

总结

不应忽视 awk 的数值计算功能, 它能完成从简单到比较复杂的数值运算。 尤其当计算过程中涉及到数据文件的处理, 这时使用 awk 往往会很方便。 因为 awk 本身有很强的文本处理功能, 它可以轻松地把数据从文本中分离出来, 然后再进行相应的计算。 本文的实例说明了如果能灵活地使用 awk 的这些功能, 有可能会显著地提升我们的工作效率。

时间: 2024-11-05 14:38:37

利用 AWK 的数值计算功能提升工作效率(转载)的相关文章

想提升工作效率,就別再做这七件事

试想一位小公司老板每日孜孜不倦地工作,为何不能从为数众多的竞争者脱颖而出? 一位创业家可以不眠不休一天工作24 小时,整整一周不休假. 然而,时间有限,且竞争者却永远可以投入更多钱与心力,让竞争更剧烈.那么,为什么某些小型新创公司可以完成许多大型企业无法完成的事情呢? ●Instagram──只有13 名员工却被Facebook 用几十亿买下的公司. ●Snapchat──只有30 名员工却拒绝科技巨人Facebook.Google 的并购交易. 它们的成功部分来自于幸运──其余则是因为效率 .

我是如何用leangoo协作工具提升工作效率的

其实,很早以前,我是一个混子.一天不知道该干什么,或者说做了这个不知道接下来该干嘛! 2013年,我和我的2个朋友一起走向了创业的道路.也是从那一天开始,我从一个混子逐渐向团队化运作,2015年,相继又有小伙伴的加入,让我们这个团队越来越壮大. 自从组建团队后,对协同办公的工具是越来越依赖,之前也分享过很多工具,但是最终用下来的还是leangoo. 没有最好的工具,只有最适合自己的工具! 请往下看: 以前我一个人,一人吃饱全家不饿,用什么工具到也是次要的,也很少推荐.后面随着越来越多的小伙伴加入

如何有效利用点晴项目管理模块提高工作效率

如何有效利用点晴项目管理模块提高工作效率 一款好的项目管理工具,是产品研发进度把控.团队协作的贤内助.用好了,将达到事半功倍的效果:用不好,不但无法提高效率.带来帮助,反而成为工作中的负担. 项目管理的作用对象是团队,因此,好的项目管理工具应该达到团队成员人人受益.提高每个成员工作效率的效果: 对领导,可掌控项目的整体情况:可查看汇总信息,包括但不限于项目进度汇总:每个成员的任务情况.项目任务反馈汇总等. 对员工,可掌控自己的具体工作:可查看自己的工作任务:可直观地查看自己当前的任务量:对于在完

如何提升工作效率?

请你告诉我,我该走哪条路?”爱丽丝说. “那要看你想去哪里?”猫说. “去哪儿无所谓.”爱丽丝说. “那么走哪条路也就无所谓了.”猫说. 引入一个经典的例子,是想告诉大家也是小编自勉,工作首先需要有目标,如果自己都不知道干什么,别人是无法帮助你的.在工作中,如果没有目标,往往是被动的完成一些工作上的事情,可能存在的问题是,工作2~3年,依旧是原地踏步.有了目标也就有了工作道路上的灯塔,知道了该选择哪条路了,即使道路崎岖和遇阻,也不会轻言放弃,因为在灯塔的指引下,有了向前冲的激情和动力. 如何制定

6个常用Excel函数,帮你进一步提升工作效率,职场必备!

我们处理Excel数据报表时候,经常因为对函数的不熟练,导致我们在插入函数时候出现不显示情况. 那么我们如何才能避免这些情况呢?不用担心今天为大家整理了6个我们办公常用到的Excel函数,学会巧妙使用它们轻松帮你进一步提升工作效率,职场必备良品之一! 获取日期里面是星期几 大家都是到在Excel里面获取日期是[Ctrl+:],但却并不知道如何才能从日期里面获取今天是周几,这时候不妨试试这个函数公式. 获取星期函数公式=TEXT(A2,"AAAA") 获取数据排名 如何才能将Excel里

Word2003中10个让你提升工作效率的技巧

虽说Word2010的出现增添了许多新功能,新用法,但是Word2003依旧不过时.相信大多数资深的办公族们目前电脑上装的依然是Word2003版本,毕竟这么多年了,用着也顺手.为方便大家使用时更顺手,下面学习啦为大家推荐10个快速输入技巧,可以帮助大家在工作中提高工作效率! 1.快速输入数字中的小数点 审计人员在结束现场审计工作,编制审计报告时,需要输入大量的审计数据,你如果是用安装Office时携带的五笔字型或拼音输入法,会为输入数字中的小数点而在中文与英文输入法间不断调整而烦恼(使用陈桥五

16款有助于提升工作效率的工具

市面上旨在提高工作效率的应用数以千计,但并非每款都真的那么好用.但愿本文介绍的16款效率工具,能够帮助你在新的一年里获得事业成功. 本文为与<创业者>杂志的合作内容,下文最初发表于Entrepreneur.com网站. 创业者之间竞争的本质在于效率.好消息是,如今市面上已经有了好几千种优秀的应用软件,能令我们的生活变得更加轻松,但是你不可能有足够的时间把这几千种应用都试上一遍.那么,哪些应用值得你花时间试用一下呢? 本文列举了16种我本人几乎每天都会使用的应用软件,我还将在本文中讨论为什么你也

mac 如何安装photoshop cc 2017 ?作为前端切图仔如何利用它来提高我们的工作效率?

作为前端切图仔一名,或多或少要与ps打上交到,你如果是大厂的话,可能不需要,小厂也有不需要的.这里是需要自己抠图的小伙伴的干活. 如何利用ps 提高我们的工作效率: 首先我们需要安装下载 photoshop cc 2014版本以上: window 下可直接在百度软件中心下载(这里我为聪明的朋友贴上地址): http://rj.baidu.com/soft/detail/40767.html 本屌是mac,搞起来就比较费劲,通常来说也是很简单的,但是我安装时候会发生201 错误,这就比较尴尬, 找

10个提升工作效率的Secure CRT小窍门 - 你玩转了几个?

10个SecureCRT 小窍门 - 你玩转几个? SecureCRT,相信不用我过多介绍了吧,一款通过telnet,ssh登录远端设备的终端软件. 无论是搞网络的,做系统的甚至写程序的,连接设备必用软件,容易上手,稳定性高,功能强大. 但是,面对SecureCRT密密麻麻的功能菜单,大家熟悉几个? 别把SecureCRT用成Putty 让我猜猜你平时怎么使用SecureCRT. 第一步:打开软件. 第二步:点开左边的会话管理栏,选择你要连接的设备. 第三步:双击连接,走你! 第四步:开始弹键盘