linux: awk

awk 是一种对立的编程语言,集成于所有UNIX/Linux中,这个名字是它创建者的名字首字母组成的 Alfred Aho,Peter Weinberger, and Brian Kernighan。

awk的基本语法

普通模式
awk '/pattern/{action}' files

其中patter是一个正则表达式,action又是一系列命令,对于满足匹配的文本执行一些动作,files表示待操作的文件,如果不指定,则输入是STDIN。如果不指定pattern,则对所有文件的每一行都执行action。

表达式模式

当在awk中使用比较操作符时,使用下面的语法模式,详见后面。

awk '(expression){action}' files

有如下一个示例文件

zdd.txt包含如下内容

Fruit Price/lbs
Banana 0.89
Paech 0.79
Kiwi 1.50
Pineapple 1.29
Apple 0.99

显示一个文件的所有行

awk '{ print ; }' zdd.txt 

分号表示命令结束,这个例子没有pattern,只有action

域编辑

awk自动将读入的行分割成域(field),域是由一个或多个分隔符分割开的字符集,缺省的分隔符是tab和空格,访问域可以用$1,$2, ... $n的形式,域都是从1开始的,而$0表示整个行(以行本来的面目呈现)

格式化输出水果及价格

awk '{ printf "%-15s %s\n", $1, $2 ;}' zdd.txt

输出如下

Fruit Price/lbs
Banana 0.89
Paech 0.79
Kiwi 1.50
Pineapple 1.29
Apple 0.99

使用其他的域分隔符

awk的-F参数可以制定其他的域分隔符,比如下面的代码将打印D

echo A:B:C:D | awk -F: '{print $4}'
多个命令同时执行

在价格高于1美元的水果后面加* 以引起注意,这里包含了两个模式和动作对,直接书写即可,不必像sed那样加-e参数

awk '/[1-9]\.[0-9][0-9]$/ { print $0, "*"} /0\.[1-9][1-9]/ {print ;}' zdd.txt

输出如下

Banana 0.89
Paech 0.79
Kiwi 1.50 *
Pineapple 1.29 *
Apple 0.99
bash-3.2$

比较操作

awk中可以执行的比较操作有
<
>
<=
>=
!=
value ~ /pattern/
value !~ /pattern/

比较操作基本语法
awk '(expression){action}' files

其中expression是一个比较表达式,通常将其用括弧括起来。

在价格大于1美元的水果后面打印expensive

awk '$2 >= 1.0 { printf "%s\t%s\n", $0, "Expensive" ; }' zdd.txt

输出

Fruit Price/lbs Expensive
Kiwi 1.50 Expensive
Pineapple 1.29 Expensive

复合表达式

可以使用&&或||连接多个表达式,表达式用()扩起
(expr1) && (expr2)
(expr1) ||(expr)

next命令
看一个例子

awk '
$3 <= 75 { printf "%s\t%s\n",$0,"REORDER" ; }
$3 > 75 { print $0 ; }
' zdd.txt

这个命令的执行过程如下
(1) 读入一行,检查价格是否小于等于75,如果为真,则打印出REORDER
(2) 检查该行是否大于75,如果大于则直接打印
(3) 处理下一行
可见如果条件(1)满足,则不必再判断条件(2)了,如果避免这个多余的操作呢?使用next即可

awk '
$3 <= 75 { printf "%s\t%s\n",$0,"REORDER" ; next ; }
$3 > 75 { print $0 ; }
' zdd.txt
BEGIN和END

基本语法

awk '
    BEGIN { actions }
    /pattern/ { actions }
    /pattern/ { actions }
    END { actions }
' files

注意BEGIN对应的模式必须是第一个模式,而END对应的模式必须是最后一个模式。这两者都不参与文本行的处理,只是做一些初始化及善后工作。

BEGIN可以用来打印表头或者列名等,如下

BEGIN{
-F":"
printf "----------------------------------------------------------------\n"
printf "%-20s%-16s  Jan  |  Feb  |  Mar  |Total Donated\n ","NAME","PHONE"
printf "----------------------------------------------------------------\n"
}

流控制

if

基本格式

if (expression1) {
    action1
} else if (expression2) {
    action2
} else {
    action3
}

一个例子,根据每行的特征字,在行末加注释。

awk '{ 
    print "%s\t", $0;
    if ($1 ~ /d/) {
        print "Directory\n";
    }
    else if ($NF ~ /\.pl/){
        print "Perl script\n";
    }
    else if ($NF ~ /\.bcp/) {
        print "BCP file\n";
    }
    else {
        print "\n";
    }
}'
while
for

awk中的for与C语言中的for类似。

awk '{ 
    for (x = 1; x <= NF; x++){
        printf "%s ", $x;
    }
    print "\n";
}' input_file ;

特殊技巧

NR==FNR

这条语句只有在输入是多个文件的时候才有意义,用来判断当前正在处理第一个文件。

NR 处理过的文件行数,多个文件累加。

FNR 处理过的文件行数,仅限当前文件。

所以,NR >= FNR。看一个例子

#cat a
张三|000001
李四|000002

#cat b
000001|10
000001|20
000002|30
000002|15

想要得到的结果是将用户名,帐号和金额在同一行打印出来,如下:

张三|000001|10
张三|000001|20
李四|000002|30
李四|000002|15

awk -F'|' 'NR==FNR{a[$2]=$0;next}{print a[$1] FS $2}' a b
awk -F'|' '{a[$2]=$0}NR>FNR{print a[$1] FS $2}' a b

[解析]
由NR=FNR成立,判断当前读入的是第一个文件a,然后使用{a[$2]=$0;next}循环将a文件的每行记录都存入数组a,并使用$2作为下标引用.next,不在执行后面的语句.
由 NR=FNR不成立,判断当前读入了第二个文件b,然后跳过{a[$2]=$0;next},对第二个文件b的每一行都无条件执行{print a[$1]FS$2},此时变量$1为第二个文件的第一个字段,与读入第一个文件时,采用第一个文件的$2为数组下标相同.因此可以在此输出该数组的值。

awk应用

按条件打印文件

awk配合ls命令可以打印文件指定的某一列,ls -l的输出入下

-rwxr-xr-x   1 user1     staff       1805 Dec  4 22:59 abc.sh
drwxr-xr-x   3 user2     staff        512 Dec  4 22:59 test_report
-rwxr-xr-x   1 user3     staff      12526 Feb  1 03:12 test.pl
drwxr-xr-x   3 user1     staff        512 Feb  1 03:19 xyz

如果只想打印文件名(第九列),那么可以使用下面的方法,$9表示文本行的第九列。

ls -l | awk '{print $9;}'

如果只想打印user1创建的文件名,可以使用下面的方法,这里/user1/是一个pattern,表示只处理包含user1的文本行。

ls -l | awk '/user1/{print $9;}'
格式化打印

awk支持printf格式化打印。

只打印文件名和文件大小(文件名位于第9列,文件大小位于第5列)

ls -l | awk '{print $9, $5;}'

上面的代码虽然能打印,但是格式很乱,可以使用printf格式化一下。

%s参数,用来打印字符串,可以指定宽度,不足的补空格,正数表示右对齐,负数表示左对齐。%3s表示字符串宽度为3列,右边对齐,如果字符串实际宽度大于3,那么取实际宽度。

文件名左对齐,大小左对齐

ls -l | awk '{printf "%-16s%\t%-16s\n", $9, $5;}'

文件名左对齐,大小右对齐

ls -l | awk '{printf "%-16s%\t%16s\n", $9, $5;}'

文件名右对齐,大小左对齐

ls -l | awk '{printf "%16s%\t%-16s\n", $9, $5;}'

文件名右对齐,大右左对齐

ls -l | awk '{printf "%16s%\t%16s\n", $9, $5;}'
按行打印环境变量PATH
echo $PATH | awk -F: ' {
    for (i = 1; i <=NF; i++) {
        printf "%s\n", $i;
    }
}'
删除某个用户的所有文件

删除用户zdd的所有文件,注意-rf后面有一个空格。

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

推荐阅读更多精彩内容

  • linux awk命令详解 来源:ggjucheng 链接:http://www.cnblogs.com/ggju...
    meng_philip123阅读 853评论 0 1
  • 简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤...
    ad085d162310阅读 1,118评论 0 1
  • awk介绍awk变量printf命令:实现格式化输出操作符awk patternawk actionawk数组aw...
    哈喽别样阅读 1,546评论 0 4
  • sed工具简介 用法:sed [-nefri] 动作参数:-n:使用安静模式(Silent)模式,一般在sed的...
    Bloo_m阅读 991评论 0 1
  • AWK 官方手册:http://www.gnu.org/software/gawk/manual/gawk.htm...
    姜淑均阅读 513评论 0 2