Shell编程-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 %sn",$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是一个比较表达式,通常将其用括弧括起来。 awk '$2 >= 1.0 { printf "%st%sn",$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 "%st%sn","REORDER" ; } $3 > 75 { print $0 ; } ' zdd.txt 这个命令的执行过程如下 (1) 读入一行,检查价格是否小于等于75,如果为真,则打印出REORDER (2) 检查该行是否大于75,如果大于则直接打印 (3) 处理下一行 可见如果条件(1)满足,则不必再判断条件(2)了,如果避免这个多余的操作呢?使用next即可 awk ' $3 <= 75 { printf "%st%sn","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 Donatedn ","NAME","PHONE" printf "----------------------------------------------------------------n" } 7 以STDIN作为输入 ls -l | awk '{ printf "%15s%15sn",$9,$5}' ipck 1853 ipcrm.exe 5632 ipcs.exe 14336 join.exe 52224 kill.exe 10240 less.exe 168960 lessecho.exe 6144 lesskey.exe 9728 link.exe 42496 lkbib.exe 52224 ln.exe 114688 locate.exe 122880 login.exe 20992 logname.exe 41472 lookbib.exe 51712 lpr.exe 299008 ls.exe 122368 makeinfo.exe 191488 man.exe 37376 man2dvi 409 man2html.exe 45568 manlint 7098 流控制if基本格式 if (expression1) { action1 } else if (expression2) { action2 } else { action3 } 一个例子,根据每行的特征字,在行末加注释。 whileforawk中的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
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 [解析] 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%-16sn",$5;}' 文件名左对齐,大小右对齐 ls -l | awk '{printf "%-16s%t%16sn",$5;}' 文件名右对齐,大小左对齐 ls -l | awk '{printf "%16s%t%-16sn",$5;}' 文件名右对齐,大右左对齐 ls -l | awk '{printf "%16s%t%16sn",$5;}' 按行打印环境变量PATHecho $PATH | awk -F: ' { for (i = 1; i <=NF; i++) { printf "%sn",$i; } }' 删除某个用户的所有文件删除用户zdd的所有文件,注意-rf后面有一个空格。 ls -l | awk '/zdd/{print "rm -rf " $9} | sh (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |