awk 从入门到精通

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/play_chess_ITmanito/article/details/77967990

1、简介
主要用来处理文本数据,处理效率高(于shell),代码简洁高效,绝对不会遇到内存溢出

2、命令处理模式:
按行处理,一行一行执行(和shell一样)
3、命令格式:

awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
-F指定分隔符 -f调用脚本      -v定义变量 var=value
'  '          引用代码块(''单引号)
BEGIN   初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
//           匹配代码块,可以是字符串或正则表达式
{}           命令代码块,包含一条或多条命令
;        多条命令使用分号分隔
END      结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息

4、awk正则:

$0           当前所在行
$n           每行第n个字段(打印列)  n可以换成任一正整数
NF          字段数量变量
NR          每行的记录号,多文件记录递增
FNR        与NR类似,不过多文件记录不递增,每个文件都从1开始
\t            制表符
\n           换行符
FS          BEGIN时定义分隔符
RS       输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
~            匹配,与==相比不是精确比较
!~           不匹配,不精确比较
==         等于,必须全部相等,精确比较
!=           不等于,精确比较
&&      逻辑与
||             逻辑或
+            匹配时表示1个或1个以上
/[0-9][0-9]+/   两个或两个以上数字
/[0-9][0-9]*/    一个或一个以上数字
FILENAME 文件名
OFS      输出字段分隔符, 默认也是空格,可以改为制表符等
ORS        输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]'   定义三个分隔符
-F":#/"

5、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)跟上面的是一样的

6、操作
最近登录账户的查看:(-F指定分隔符仅支持:不加”“,其它分隔符不加”“全部不识别)

last -n 2 | awk  '{print $1}'      //print打印指定内容

awk '{print}'  /etc/passwd  等于  awk '{print $0}'  /etc/passwd  等于  cat /etc/passwd

awk '{print " "}' /etc/passwd       //不输出passwd的内容,而是输出相同个数的空行,进一步解释了awk是一行一行处理文本

awk '{print "a"}'   /etc/passwd     //输出相同个数的a行,一行只有一个a字母
awk -F":" '{print $1}'  /etc/passwd
awk -F: '{print $1}'  /etc/passwd
awk -F'[:]' '{print $1}'  /etc/passwd


awk -F"/" '{print $2}'  /etc/passwd
awk -F: '{print $1; print $2}'   /etc/passwd(换行显示)    等于  awk -F: '{print $1, $2}'(不换行)   /etc/passwd//将每一行的前二个字段,分行输出,进一步理解一行一行处理文本
awk  -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd  //指定以tab键分隔第1,3,6个字段    OFS指定分隔符

7、变量:-v
(1)内置变量

ARGC               命令行参数个数
ARGV               命令行参数排列
ENVIRON            支持队列中系统环境变量的使用
FILENAME           awk浏览的文件名
FNR                浏览文件的记录数
FS                 设置输入域分隔符,等价于命令行 -F选项
NF                 浏览记录的域的个数
NR                 已读的记录数
OFS                输出域分隔符-F
ORS                输出记录分隔符
RS                 控制记录分隔符

统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:

#awk  -F '/'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:29,columns:6,linecontent:saslauth:x:498:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
filename:/etc/passwd,linenumber:30,columns:6,linecontent:postfix:x:89:89::/var/spool/postfix:/sbin/nologin
filename:/etc/passwd,linenumber:31,columns:6,linecontent:pulse:x:497:496:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
filename:/etc/passwd,linenumber:32,columns:6,linecontent:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
filename:/etc/passwd,linenumber:33,columns:4,linecontent:tcpdump:x:72:72::/:/sbin/nologin

打印:文件名,行数,字段数,当前行内容:

awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
awk  -F ':'  '{printf("filename:%s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
awk  -F ':'  '{printf "filename:"FILENAME",linenumber:"NR",columns:"NF",linecontent:"$0"\n"}' /etc/passwd

%10s:
输入时,%10s表示最多接受10个字符,多余的忽略;
输出时,%10s表示字符串长度不足10个时,左边补空格,保证占10个字节位置,10个及以上原样输出.

print和printf:
awk中同时提供了print和printf两种打印输出的函数。
print函数的参数:变量、数值或者字符串。(字符串必须用”“引用,参数用,分隔。如果没有, ,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。)
printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。
(2)自定义变量:
统计虚拟机/etc/passwd用户数量:

awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd

8、awk实现wordcount(词频统计)案例

vi a.log
my name is hahah .
14 years old
运行方式一:
vi wc.awk

{
  for (i = 1; i<=NF; i++)
    freq[$i]++
}
END{
  for (word in freq)
    printf "%s%d\n",word,freq[word]
}
运行:
awk -f wc.awk a.log
运行方式二:
vi wordcount_awk.sh
#!/bin/sh
awk -F " " '{
  for (i = 1; i<=NF; i++)
    freq[$i]++
}
END{
  for (word in freq)
    printf "%s%d\n",word,freq[word]
}' $1

执行:
chmod u+x wordcount_awk.sh
./wordcount_awk.sh f.txt

9、打印九九乘法表

seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}'

猜你喜欢

转载自blog.csdn.net/play_chess_ITmanito/article/details/77967990