您的位置:首页 > 编程语言

编程 -- awk

2016-03-14 17:07 344 查看
小Q:孤独不是与生俱来的,而是由你爱上一个人的那一刻开始。
============================================================
一:简介
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk做大的优势。
二:调用方式
1.命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
3.将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
三:入门实例
1. 只显示/etc/passwd的账户 ==== 查询

#cat /etc/passwd |awk  -F ':'  '{print $1}'
root
daemon
bin
sys
这种是awk+action的示例,每行都会执行action{print $1}。
2. 只显示/etc/passwd的账户和账户对应的shell,而他们之间以tab键分割 分隔符=== OFS

#cat /etc/passwd |awk  -F ':'  '{print $1"\t"$7}'
root    /bin/bash
daemon   /bin/sh
bin     /bin/sh
sys     /bin/sh
===#cat /etc/passwd |awk  -F ':'  '{print OFS=“\t”}{print $1,$7}'
===#cat /etc/passwd |awk  -F ':'  'BEGIN{print OFS=“\t”}{print $1,$7}'
3. 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。 ====== BEGIN END

cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"}{print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh
awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
4. 搜索/etc/passwd有root关键字的所有行 查询======= '/ ...../ '

#awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
搜索支持正则,例如找root开头的: awk -F: '/^root/' /etc/passwd
5. 搜索/etc/passwd有root关键字的所有行,并显示对应的shell 查询并打印指定的域

# awk -F: '/root/{print $7}' /etc/passwd
/bin/bash
#这里指定了action{print $7}
四:awk内置变量
awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。
1. 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容: ===FILENAME

#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}'
/etc/passwdfilename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
= awk -F ':''{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
##特: 使用printf替代print,可以让代码更加简洁,易读                    === printf
2. 统计每行共有几个域,打印出每行第几个域;已读第几个域,并依行打印第几个域 == NS NF



3. 将输出内容以一行并用 | 分隔打印 === ORS printf

#awk  -F':' '{ORS="|"}{print $1}' /etc/passwd
root|bin|daemon|adm|lp|sync|shutdown|halt|mail|news|
#==awk  -F':' ‘{printf (“%s,”,$1)}’ /etc/passwd
#awk  -F':' '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
4. 将输出以%格式分隔 === OFS

head /etc/passwd |awk -F':' 'BEGIN{OFS="%"}{print $1,$2}'
root%xbin%xdaemon%xadm%xlp%xsync%xshutdown%xhalt%xmail%xnews%x
五:awk的运算

算术运算符




例: awk 'BEGIN{a="b";print a++,++a;}' 0 2
注意:所有用作算术运算符进行操作,操作数自动转为数值,所有非数值都变为0

赋值运算符

= += -= *= /= %= ^= **= 赋值语句

例: a+=5; 等价于:a=a+5; 其它同类

逻辑运算符

|| 逻辑或 && 逻辑与

例: awk 'BEGIN{a=1;b=2;print (a>5 && b<=2),(a>5 || b<=2);}' 0 1

正则运算符

~ ~! 匹配正则表达式和不匹配正则表达式

例: awk 'BEGIN{a="100testa";if(a ~ /^100*/){print "ok";}}' ok

关系运算符

< <= > >= != == 关系运算符

例: awk 'BEGIN{a=11;if(a >= 9){print "ok";}}' ok

注意:> < 可以作为字符串比较,也可以用作数值比较,关键看操作数如果是字符串就会转换为字符串比较。两个都为数字才转为数值比较字符串比较:按照ASCII码顺序比较。
其它运算符




例: awk 'BEGIN{a="b";print a=="b"?"ok":"err";}' ok

awk 'BEGIN{a="b";arr[0]="b";arr[1]="c";print (a in arr);}' 0

awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print (a in arr);}' 1



运算级优先级表 级别越高越优先 级别越高越优先
六:awk编程

1. 传递和定义变量+赋值

借助-v 选项,可以将外部值(并非来自stdin)传递给awk:

VAR=10000

echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'

另一种传递外部变量方法:

var1="aaa" var2="bbb"
echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2

当输入来自于文件时使用:
awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename

以上方法中,变量之间用空格分隔作为awk的命令行参数跟随在BEGIN、{}和END语句块之后。
下面统计/etc/passwd的账户人数

awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
......
user count is  40
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。
这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:

awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
[start]user count is  0
root:x:0:0:root:/root:/bin/bash
...
[end]user count is  40
2. 条件判断语句

例一. awk分枝结构允许嵌套,其格式为:
if(表达式)

{语句1}
else if(表达式)

{语句2}

else {语句3}

示例:

awk 'BEGIN {

test=100;

if(test>90) {
print "very good"; }
else if(test>60) {

print "good"; }

else{ print "no pass"; } }' very good 每条命令语句后面可以用 ; 分号结尾。
例二. 统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹)
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.22339 M
3. 循环语句

例一:while语句

while(表达式)
{语句}

示例:

awk 'BEGIN {

test=100; total=0;

while (i<=test) {

total+=i; i++; }

print total; }' 5050

例二:for循环

for循环有两种格式:

格式1: for(变量 in 数组) {语句}
示例:

awk 'BEGIN {

for (k in ENVIRON) {
print k"="ENVIRON[k]; } }'
TERM=linux

G_BROKEN_FILENAMES=1

SHLVL=1

pwd=/root/text ...

logname=root 注:ENVIRON是awk常量,是子典型数组
格式2:for (变量;条件;表达式) {语句}

示例: awk 'BEGIN {

total=0 ;
for(i=0;i<=100;i++){
total+=i; }
print total; }' 5050
七:数组 字符串 函数

.....................................................................................................................

tips :
1. awk 默认不能直接使用花括号
正则表达式中,有一个用法就是一个字符或者一串字符的重复次数。比如(abc){1,3}
表示含有 abc abcabc abcabcabc 这样的行都会匹配到
awk 直接这样用是匹配不到东西的
awk '/(abc){1,3}/' 1.txt
这是因为在awk中()和{}都有特殊的含义,需要做个特殊处理才可以:
awk --posix '/(abc){1,3}/' 1.txt
2. 在awk中调用系统变量必须用单引号,如果是双引号,则表示字符串

推荐:http://www.cnblogs.com/emanlee/p/3327576.html
官方:http://www.gnu.org/software/gawk/manual/gawk.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux command awk