awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说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/awk3.将所有的awk命令插入一个单独文件,然后调用:awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。

如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。

awk的用法大全_awk用法

cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'name,shell
root,/bin/bash
daemon,/bin/shbin,/bin/shsys,/bin/sh....
blue,/bin/nosh

awk的用法大全_awk用法

awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

 

搜索/etc/passwd有root关键字的所有行

#awk -F: '/root/' /etc/passwdroot:x:0:0:root:/root:/bin/bash

这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。

搜索支持正则,例如找root开头的: awk -F: '/^root/' /etc/passwd

 

搜索/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                 控制记录分隔符

awk的用法大全_awk用法

 此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。

 

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

#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/shfilename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/shfilename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh

 

使用printf替代print,可以让代码更加简洁,易读

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

 

print和printf

awk中同时提供了print和printf两种打印输出的函数。

其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。

 

 awk编程

 变量和赋值

除了awk的内置变量,awk还可以自定义变量。

下面统计/etc/passwd的账户人数

  /etc/::root:/root:/bin/

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  0root:x:0:0:root:/root:/bin/bash
...
[end]user count is  40

 

统计某个文件夹下的文件占用的字节数

 -l |

 

如果以M为单位显示:

 -l |  
[end]size is  8.25889 M




Awk的输出:

Print item1item2

要点

   如果 print后面没有数据就是显示$0

print item1, item2,...

     要点:

     (1) 各项目之间使用逗号分隔,而输出时则使用输出分隔符分隔;

     (2) 输出的各item可以字符串或数值、当前记录的字段、变量或awk的表达式;数值会被隐式转换为字符串后输出;

     (3) print后面item如果省略,相当于print $0;输出空白,使用pirnt""

 -Fchar :输入分隔符

 例如:

显示用户名  

awk的用法大全_awk用法_04

awk的用法大全_awk用法_05

  显示的是全部内容

Awk的内置变量在BEGIN中定义

   A: FS: 输入时字段分隔符

awk的用法大全_awk用法_06

RS :输出时的分隔符

OFS:输出时的字段分隔符

awk的用法大全_awk用法_07

显示的内容会把:当做分隔符形成一个文件形式的显示出来

NF:每行的字段数   NR: 行数,所有文件一并统计

FNR:统计当前文件{个文件分别计数}

awk的用法大全_awk用法_08

ARGV:数组,保存命令本身这个字符,awk '{print $0}' 1.txt 2.txt,意味着ARGV[0]保存awk,

ARGC: 保存awk命令中参数的个数;

FILENAME awk正在处理的当前文件的名称

例子:

  awk的用法大全_awk用法_09

2.2 可自定义变量

       -v var_name=VALUE

变量名区分字符大小写;

(1) 可以program中定义变量;

       (2) 可以命令行中通过-v选项自定义变量;

      3awkprintf(打印格式)命令

      命令的使用格式:printfformat, item1, item2,...

      要点:

       (1) 要指定format(格式);

       (2) 不会自动换行;如需换行则需要给出\n

       (3) format用于为后面的每个item指定其输出格式;

format格式的指示符都%开头,后跟一个字符:

            %c: 显示字符的ASCII码;

            %d, %i: 十进制整数;

            %e, %E: 科学计数法显示数值;

            %f: 显示浮点数;

            %g, %G: 以科学计数法格式或浮点数格式显示数值;

            %s: 显示字符串;

            %u: 显示无符号整数;

            %%: 显示%自身;

%与字母之间还可以加让你修饰符

       修饰符:

            #:显示宽度

            -:左对齐

            +:显示数值的符号

            .#: 取值精度

 

awk的用法大全_awk用法_10

awk的用法大全_awk用法_11

当后面的数字不够时补零

4awk输出重定向

       print items > output-file

       print items >> output-file

       print items | command

 

       特殊文件描述符:

       /dev/stdin: 标准输入

       /dev/stdout: 标准输出

       /dev/stderr: 错误输出

 

5awk的操作符

 

       算术操作符:

            x+y:相加

            x-y:相减

            x*y:相乘

            x/yx除以y

            x**y, x^yxy次方

            x%y1去摸运算

            -x:负值

            +x:转换为数值

 

       字符串操作符:连接

 

       赋值操作符:

            = += -= *= /= %= ^= ++  --

如果模式自身是=号,要写为/=/

比较操作符:

            <<=>>===!=

            ~:模式匹配,左边的字符串能够被右边的模式所匹配为真,否则为假;

            !~:取相反的结果

逻辑操作符:

 

            &&  ||:或

我们来显示一个、etc/passwd下的gid>=500显示jin否者显示shuai

[root@handev]# awk-F: '{$3>=500?han="jin":han="shuai";print$3,"is",han}' /etc/passwd

、模式

 

       (1) Regexp: 格式为/PATTERN/

             仅处理被/PATTERN/匹配到的行;

       (2) Expression: 表达式,其结果为非0或非空字符串时满足条件;

             仅处理满足条件的行;

       (3) Ranges: 行范围,此前地址定界,startline, endline

             仅处理范围内的行

       (4) BEGIN/END: 特殊模式,仅在awk命令的program运行之前(BEGIN)或运行之后(END)执行一次;

       (5) Empty:空模式,匹配任意行;

  、控制语句

 

       8.1 if-else

             格式:if (condition) {then body} else {else body}

  例子:如果gid>=500 显示用户名后加上isa common user否者后面加上is an admin or system user

             # awk -F: '{if ($3>=500) {print$1,"is a common user"} else {print $1, "is an admin or systemuser"}}' /etc/passwd

显示/etc/inittab下字段数大于等于8的哪一行              

# awk'{if (NF>=8) {print}}' /etc/inittab

 

       8.2 while

             格式:while (condition) {while body}

        例子:显示当i小于等于自己的字段数时就显示字符串(为单数的)行

             # awk '{i=1; while(i<=NF){printf "%s ",$i;i+=2};print ""}' /etc/inittab

      例子:当i小于等于自己的字段数且长度小于6时,做累加显示其行数

             # awk '{i=1; while (i<=NF){if(length($i)>=6) {print $i}; i++}}' /etc/inittab

awk的用法大全_awk用法_12

length()函数:取字符串的长度

 

       8.3 do-while循环

             格式:do {do-while body} while (condition)

 

       8.4 for循环

             格式:for (variable assignment; condition; iteration process) {for body}

             # awk '{for(i=1;i<=NF;i+=2){printf "%s ",$i};print ""}'/etc/inittab

             # awk '{for (i=1;i<=NF;i++){if(length($i)>=6) print $i}}' /etc/inittab

awk的用法大全_awk用法_13