您的位置:首页 > 运维架构 > Shell

awk命令用法入门--获取股票信息

2017-07-19 15:42 281 查看

起源用途

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。awk是一个强大的文本分析工具,尤其善于处理多行表格式文本,并生成报告.awk不仅仅是一个工具,也可以认为是一门语言。

awk与sed的区别

Awk、sed与grep,俗称Linux下的三剑客,它们之间有很多相似点,但是同样也各有各的特色,相似的地方是它们都可以匹配文本,其中sed和awk还可以用于文本编辑,而grep则不具备这个功用。sed是一种非交互式且面向字符流的编辑器(a "non-interactive" stream-oriented editor),而awk则是一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并处理,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等,当然比起我们常见的编程语言,Awk相对比较简单。

命令格式

awk [-F  field-separator]  'commands'  input-file(s)commands结构: 'BEGIN {awk-commands} /pattern/ {awk-commands} END {awk-commands}'commands由3部分组成,BEGIN块,主体块 (body block),END块,每个块都是可选的.每个块(block)都由大括号{}包含,可以拥有多条语句,每条语句使用分号";"进行分割主体块比开始结束块多一个pattern部分/pattern/ {awk-commands}用作匹配.注意:主体块可以有多个,每一行会依次执行主体块,如文件有m行,主体块有n个,则主体块会执行m*n次

awk工作流程

通过关键字BEGIN执行begin块的内容,即BEGIN后花括号{}的内容.完成begin块的执行,开始执行body块.读入有'\n'换行符分割的记录将记录按指定的域分隔符划分域,填充域,$0则表示所有域(即一行内容),$1表示第一个域,$n表示第n个域。依次执行各body块,pattern部分匹配该行内容成功后,才会执行awk-commands的内容.循环读取并执行各行直到文件结束,完成body块执行.开始END块执行,END块可以输出最终结果.

例子1

sw@:ipc$ whoroot     tty7         2017-04-26 10:06 (:0)sw       pts/0        2017-06-11 10:41 (192.168.20.81)sw@ipc$ who |awk 'BEGIN {print "idx user ttyname"} {printf("%3d %4s %5s\n",NR,$1,$2)} END {print "====++++======"}'idx user ttyname1 root  tty72   sw pts/0====++++======sw@tomato:ipc$ who |awk '{print $1}{print $2}'roottty7swpts/0
BEGIN关键字后面大括号{}内容表示在数据分割前执行,上面的例子用来打印题头END关键字后面大括号{}内容表示数据处理结束后执行,上面例子用来打印结束分割print函数与printf函数都可以使用,print函数较处理简单情况比较方面,printf做格式控制和c语言一致.NR为内置变量,内置变量引用不需要加变量引用符$BEGIN后面的第一个大括号{}会被解析为begin块内容,其后到END之前的大括号{}内容都会当成body块执行.

例子2

sw@tomato:ipc$ awk 'BEGIN {a=3;b=4;printf("result:%d mode:%d\n",a+(3*b)/2-5,a%b)}'result:4 mode:3sw@tomato:ipc$ awk 'BEGIN {a=3;b=a;a++;b-=1;printf("result:%d \n",a^=b)}'result:16sw@tomato:ipc$ awk 'BEGIN \{\for(i=0;i<5;i++)\{\a[i] = i**2;\switch(i)\{\case 2:\printf("error\n");\break;\default:\printf("a[%d]:%d\n",i,a[i]);\}\}\}'a[0]:0a[1]:1errora[3]:9a[4]:16
 awk命令的块都是可选的,上面例子就只有begin块,这种用法可以当简单的计算器使用.语句都是由分号分割,一个块中可以包含很多语句,语句长了可以写成多行用反斜杠连接.语句的语法与C语言类比,基本一致,可以直接使用c语言语法变量是无显式类型的,使用前需要初始化.支持加减乘除(+-*/),前后自增自减(++i,i--),与或非(&& || !),运算赋值(+= -= *=),3元运算(a?0:1).支持指数操作,指数操作符为"^"或者"**",如上例中的a^=b与a=a**b是一致的.支持if,while,for等分值循环结构,大括号{}可以嵌套,支持数组操作注意:awk部分语法与C语言差不多,但不完全一致,且写法更灵活,可以先类比C语言语法来用,使用过程中再区分差异.

例子3

下面的使用awk脚本的例子,脚本可以使用函数.脚本基本构成还是3个block,其中body块可以有多个,下面的例子就是每读一行,使用3个body块(/pattern/ {awk-commands} )去匹配与执行命令,可以看到输出的结果按行交错输出的.sw@tomato:ipc$ cat b.txtroot:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/bin/shbin:x:2:2:bin:/bin:/bin/shsys:x:3:3:sys:/dev:/bin/shsync:x:4:65534:sync:/bin:/bin/syncsw@tomato:ipc$ ./test.awk b.txt=========11=========333   0   root      0      0222   1 daemon      1      1333   2 daemon      1      1333   3    bin      2      2111   4    sys      3      3333   5    sys      3      3111   6   sync      4  65534333   7   sync      4  65534--------------------脚本内容:sw@tomato:ipc$ cat test.awk#!/usr/bin/awk -f#awk script for test!function min(num1, num2){  if (num1 < num2)    return num1  return num2}function begin(){    printf("=========%d=========\n",min(11,22));}function body(){    printf("%2d %6s %6d %6d\n",i++,$1,$3,$4);}function end(){    printf("--------------------\n");}BEGIN {    i = 0;FS=":";begin();}/sy/{printf("111  ");body();}/m/{printf("222  ");body();}{printf("333  ");body(); }END {end();}

例子4

上班用电脑看股票价格太招摇,可以用awk整一个简单的工具查看股票信息,用的是新浪提供好的接口,命令很简单:
#!/bin/bashawk 'BEGIN {printf("  代码      现价    涨跌    开盘    最高    最低\n");}'geta(){curl "http://hq.sinajs.cn/list=$1" 2>/dev/null |iconv -t utf-8 -f gb2312 -c |sed 's/var.*=\"//g' | awk -F ',' '{printf("%s %7.2f %6.2f%s %7.2f %7.2f %7.2f\n",$1,$4,($4-$3)*100/$2,"%",$2,$5,$6)}'}geta sh000001geta sh600519
结果如下:
  代码      现价    涨跌    开盘    最高    最低上证指数 3462.08   0.44% 3419.22 3463.16 3388.86贵州茅台  740.40  -2.30%  752.22  753.23  725.00
awk的内置变量ARGC               命令行参数个数ARGV               命令行参数排列ENVIRON            支持队列中系统环境变量的使用FILENAME                       awk浏览的文件名( 开始块中FILENAME是未定义的。)FNR                浏览文件的记录数FS                 设置输入域分隔符,等价于命令行 -F选项NF                 浏览记录的域的个数NR                 已读的记录数OFS                输出域分隔符ORS                输出记录分隔符RS                 控制记录分隔符*内置变量使用的时候不需要加$变量引用符awk的内置函数gsub(reg,string,target) 每次常规表达式reg匹配时替换target中的stringindex(search,string) 返回string中search串的位置length(string) 求串string中的字符个数match(string,reg) 返回常规表达式reg匹配的string中的位置printf(format,variable) 格式化输出,按format提供的格式输出变量variable。split(string,store,delim) 根据分界符delim,分解string为store的数组元素sprintf(format,variable) 返回一个包含基于format的格式化数据,variables是要放到串中的数据strftime(format,timestamp) 返回一个基于format的日期或者时间串,timestmp是systime()函数返回的时间sub(reg,string,target) 第一次当常规表达式reg匹配,替换target串中的字符串substr(string,position,len) 返回一个以position开始len个字符的子串totower(string) 返回string中对应的小写字符toupper(string) 返回string中对应的大写字符atan(x,y) x的余切(弧度)cos(x) x的余弦(弧度)exp(x) e的x幂int(x) x的整数部分log(x) x的自然对数值rand() 0-1之间的随机数sin(x) x的正弦(弧度)sqrt(x) x的平方根srand(x) 初始化随机数发生器。如果忽略x,则使用system()system() 返回自1970年1月1日以来经过的时间(按秒计算)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux awk shell