七.Linux三剑客之awk命令

awk的调用方式与sed类似,脚本文件以#!/bin/awk -f或#!/bin/gawk -f开头。相比于grep和sed,awk正则表达式支持"?"和"+"两个拓展元字符。

  • awk模式匹配
$ cat file 
qwer


1234
[jin1ming@ML linux_shell]$ awk '/^$/{print "Hello World!"}' file 
Hello World!
Hello World!

^$在此处用于匹配空行

  • 记录和域
    awk认为每行为一个记录,行中每个字符串为域,域之间用空格,Tab键或其他符号进行分隔,分隔域的是分隔符。(分隔符默认为空格)
$ cat phoneinfo 
张三 湖南 123455
李四 山西 222222
王五 河南 333333
$ awk '{print $1}' phoneinfo 
张三
李四
王五
$ awk '{print $1;{print $0}}' phoneinfo 
张三
张三 湖南 123455
李四
李四 山西 222222
王五
王五 河南 333333
$ awk 'BEGIN{num=3} {print$num}' phoneinfo 
123455
222222
333333

n代表第n个域,0代表所有域
awk处理时,将进行逐行扫描
BEGIN在遍历文件前执行
awk中可使用变量

$ awk 'BEGIN{OFS=";"} {print $1,$2,$3}' phoneinfo | 
> awk 'BEGIN{FS=";";OFS="::"} {print $1,$2,$3}'
张三::湖南::123455
李四::山西::222222
王五::河南::333333

OFS为输出域分隔符,FS为(输入)域分隔符
该demo,将文件中的空格作为域分隔符进行域划分,
将“;”作为域分隔符进行输出到管道,
最后将管道中的文本按“;”作为域分隔符进行域划分,
最后将“::”作为输出域分隔符进行输出。

#修改字符串之间的空格为两个
$ cat phoneinfo 
张三  湖南  123455
李四  山西  222222
王五  河南  333333
$ awk 'BEGIN{OFS=","}{print $1,$2,$3}' phoneinfo 
张三,湖南,123455
李四,山西,222222
王五,河南,333333

说明空格作为域分隔符时,空格可为1个或多个

$ awk 'BEGIN{OFS="::"}{print $1,$2,$3}' phoneinfo |
> awk 'BEGIN{FS=":";OFS=","} {print $1,$2,$3}' 
张三,,湖南
李四,,山西
王五,,河南
$ awk 'BEGIN{OFS="::"}{print $1,$2,$3}' phoneinfo |
> awk 'BEGIN{FS="::";OFS=","} {print $1,$2,$3}' 
张三,湖南,123455
李四,山西,222222
王五,河南,333333

其他符号作为域分隔符只代表其一个字符,若想多个,必须使用“+”,
例如 \t+代表一个或多个该字符(支持正则)
注意此处第一个命令,输出中第二个域为空域

$ awk 'BEGIN{OFS="::"}{print $1,$2,$3}' phoneinfo |
> awk 'BEGIN{FS="::";OFS=",";ORS=";"}
> {print $1,$2,$3}' 
张三,湖南,123455;李四,山西,222222;王五,河南,333333;

ORS输出域分隔符,RS记录分隔符(默认都为换行符)

  • 关系和布尔运算符

需注意:
1:~ 匹配正则表达式
2: !~ 不匹配正则表达式
其他运算符与c语言一致

$ awk 'BEGIN{FS=":"} $2~/dd/' 2.txt 
2:dd
:ddddddd
  • 表达式
    统计行数
$ awk 'BEGIN{i=0} {print ++i}' 2.txt 
1
2
3
4
5

计算每人平均分数

$ cat score 
张三:78 92 87
李四:91 64 87
王五:34 99 56
$ cat awkdomo.awk 
#!/bin/awk -f

BEGIN {FS="[: ]"}
{sum=$2+$3+$4
avg=sum/3
print $1,":",avg}

$ chmod u+x awkdomo.awk 
$ ./awkdomo.awk score 
张三 : 85.6667
李四 : 80.6667
王五 : 63
  • 常用系统变量
    以上提到的不再重复

ARGC 命令行参数的数量
ARGIND 命令行中当前文件的位置(以0开始标号)
ARGV 命令行参数的数组(ARGV[0]存储的是执行脚本的程序名)
FILENAME 当前文件名
NF 当前记录中的域数量

$ cat awkdomo.awk 
#!/bin/awk -f

BEGIN{FS="[: ]"}

{print "\nARGC:",$ARGC,
    "\nARGIND:",$ARGIND,
    "\nARGV",$ARGV[2],
    "\nFILENAME:",$FILENAME,
    "\nNF:",$NF
}

$ ./awkdomo.awk score 

ARGC: 78 
ARGIND: 张三 
ARGV 张三:78 92 87 
FILENAME: 张三:78 92 87 
NF: 87

ARGC: 91 
ARGIND: 李四 
ARGV 李四:91 64 87 
FILENAME: 李四:91 64 87 
NF: 87

ARGC: 34 
ARGIND: 王五 
ARGV 王五:34 99 56 
FILENAME: 王五:34 99 56 
NF: 56
  • 格式化输出
    printf (格式控制符,参数) ,与c语言一致
  • 内置字符串函数

gsub(r,s) 在输入文件中用s替换r(全局替换)
gsub(r,s,t) 在t行中用s替换r
index(s,t) 返回s中字符串第一个t的位置
length(s) 返回s的长度
match(s,t) 测试s是否包含匹配t的字符串
split(r,s,t) 以t为分隔符将r进行分割,保存到数组s
sub(r,s,t) 将t中第一次出现的r替换为s
substr(r,s) 返回字符串r中从s开始的后缀部分
substr(r,s,t) 返回字符串r中从s开始长度为t的后缀部分

  • 向awk脚本传递参数
    awk -f 脚本文件 parameter=value 输入文件

    awk [awk命令] parameter=value 输入文件
$ awk '
BEGIN{n = 999; print n}
{if (n==1) print "Continue!"
} ' n=1 2.txt
999
Continue!
Continue!
Continue!
Continue!
Continue!

参数赋值在BEGIN后执行

  • 条件语句和循环语句
    和c语言完全一致,在判断时可以使用~匹配符和正则表达式作为if语句的条件
  • 数组
    awk数组的形式和c语言一致,只是无需定义就可以使用,需要注意的是数组下标不是必须为整数,可以为浮点数或字符串,而且09和9作为下标是不一样的
$ awk '
BEGIN{nums[1.5]=5.1} {print nums[1.5];print nums[1]} 
' score
5.1

5.1

5.1

$ awk '
BEGIN{nums[wer]=9;nums[2]=2;nums[9]=9} 
END {for (var in nums)
print var,":",nums[var]
}' score
 : 9
9 : 9
2 : 2

数组和参数相结合的根据姓名查询个人信息

$ cat awkdomo2.awk 
#!/bin/awk -f

BEGIN{
   if(ARGC>2){
       name=ARGV[1];
       delete ARGV[1] }
   else{
       while(!name){
           print "请输入姓名:";
           getline name< "-"}
       }
   }

   $1~name {print $1,$2,$3}
./awkdomo2.awk  张三 phoneinfo 
张三 湖南 123455

输入姓名使用read将会使得"请输入姓名:"疯狂输出,原因还尚未琢磨清楚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • awk介绍awk变量printf命令:实现格式化输出操作符awk patternawk actionawk数组aw...
    哈喽别样阅读 1,562评论 0 4
  • 转载 原文的排版和内容都更加友好,并且详细,我只是在这里贴出了一部分留作自己以后参考和学习,如希望更详细了解AWK...
    XKirk阅读 3,200评论 2 25
  • awk: grep,sed,awk grep:文本过滤 sed:文本编辑 awk:文本格式化工具; 1 什么是aw...
    木林森阅读 1,771评论 0 16
  • awk:报告生成器,格式化文本输出 内容: awk介绍 awk基本用法 awk变量 awk格式化 awk操作符 a...
    BossHuang阅读 1,453评论 0 9
  • 问:亲爱的,你平时的日用品都去哪里买? 答:附近超市买啊 问:你在那里办会员了吗? 答:办了会员。 …… 很多机构...
    许玲玲阅读 669评论 0 1