awk命令用法入门

来源:互联网 发布:淘宝网僧衣 编辑:程序博客网 时间:2024/06/10 01:06

起源用途

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

awk工作流程



  1. 通过关键字BEGIN执行begin块的内容,即BEGIN后花括号{}的内容.
  2. 完成begin块的执行,开始执行body块.
  3. 读入有'\n'换行符分割的记录
  4. 将记录按指定的域分隔符划分域,填充域,$0则表示所有域(即一行内容),$1表示第一个域,$n表示第n个域。
  5. 依次执行各body块,pattern部分匹配该行内容成功后,才会执行awk-commands的内容.
  6. 循环读取并执行各行直到文件结束,完成body块执行.
  7. 开始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 ttyname  1 root  tty7  2   sw pts/0====++++======sw@tomato:ipc$ who |awk '{print $1}{print $2}'roottty7swpts/0


  1. BEGIN关键字后面大括号{}内容表示在数据分割前执行,上面的例子用来打印题头
  2. END关键字后面大括号{}内容表示数据处理结束后执行,上面例子用来打印结束分割
  3. print函数与printf函数都可以使用,print函数较处理简单情况比较方面,printf做格式控制和c语言一致.
  4. NR为内置变量,内置变量引用不需要加变量引用符$
  5. 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
  1.  awk命令的块都是可选的,上面例子就只有begin块,这种用法可以当简单的计算器使用.
  2. 语句都是由分号分割,一个块中可以包含很多语句,语句长了可以写成多行用反斜杠连接.
  3. 语句的语法与C语言类比,基本一致,可以直接使用c语言语法
  4. 变量是无显式类型的,使用前需要初始化.
  5. 支持加减乘除(+-*/),前后自增自减(++i,i--),与或非(&& || !),运算赋值(+= -= *=),3元运算(a?0:1).
  6. 支持指数操作,指数操作符为"^"或者"**",如上例中的a^=b与a=a**b是一致的.
  7. 支持if,while,for等分值循环结构,大括号{}可以嵌套,支持数组操作
注意:awk部分语法与C语言差不多,但不完全一致,且写法更灵活,可以先类比C语言语法来用,使用过程中再区分差异.

例子3

下面的使用awk脚本的例子,脚本可以使用函数.
脚本基本构成还是3个block,其中body块可以有多个,下面的例子就是每读一行,使用3个body块(/pattern/ {awk-commands} )去匹配与执行命令,可以看到输出的结果按行交错输出的.
sw@tomato:ipc$ cat b.txt
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync

sw@tomato:ipc$ ./test.awk b.txt
=========11=========
333   0   root      0      0
222   1 daemon      1      1
333   2 daemon      1      1
333   3    bin      2      2
111   4    sys      3      3
333   5    sys      3      3
111   6   sync      4  65534
333   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();}

awk的内置变量
ARGC               命令行参数个数
ARGV               命令行参数排列
ENVIRON            支持队列中系统环境变量的使用
FILENAME                       awk浏览的文件名( 开始块中FILENAME是未定义的。)
FNR                浏览文件的记录数
FS                 设置输入域分隔符,等价于命令行 -F选项
NF                 浏览记录的域的个数
NR                 已读的记录数
OFS                输出域分隔符
ORS                输出记录分隔符
RS                 控制记录分隔符
*内置变量使用的时候不需要加$变量引用符

awk的内置函数
gsub(reg,string,target) 每次常规表达式reg匹配时替换target中的string
index(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日以来经过的时间(按秒计算)
原创粉丝点击