GNU awk基础

awk介绍

  • awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出
  • 有多种版本:New awk(nawk),GNU awk( gawk)
  • gawk:模式扫描和处理语言
  • 基本用法:

awk [options] ‘program’ var=value file…

awk [options] -f programfile var=value file…

awk [options]  ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }’  file …

awk 程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块 、END语句块,共3部分组成

program通常是被单引号或双引号中

  • 选项:

-F 指明输入时用到的字段分隔符

-v var=value: 自定义变量

 

awk不能修改文件,只做输出显示处理

 

[root@localhost ~]# which awk

/usr/bin/awk

[root@localhost ~]# ll /usr/bin/awk

lrwxrwxrwx. 1 root root 4 Dec 14 21:53 /usr/bin/awk -> gawk

 

awk语言

  • 基本格式:awk [options] ‘program’ file…
  • program:pattern{action statements;..}
  • pattern和action:

pattern部分决定动作语句何时触发及触发事件

BEGIN,END

pattern决定了是针对那种类型的行进行处理。虽然默认把每一行都读进来,但是读进来的行要不要处理,可以定义pattern进行过滤,例如:如果满足pattern就执行动作,不满足就不符合条件,就可以直接跳到下一行开始。

action statements对数据进行处理,放在{}内指明。打印显示必要的内容

print, printf

 

print:简单的把必要的内容数据显示出来

printf:更加具体详细的定义显示的格式,例如添加控制符,打印的时候字段和字段之间有多宽、小数点有多少位

 

  • 分割符、域和记录

awk执行时,由分隔符分隔的字段(域)标记,分割成若干个列,每个列系统会自动分配变量$1,$2..$n对应的表示他们,用$1,$2..$n分别表示这一行的第几列,称为域标识。$0为所有域,注意:和shell中变量$符含义不同

文件的每一行称为记录默认回车换行分割记录

省略action,则默认执行 print $0 的操作打印一整行

$0为所有域整行的所有字段

 

在bash中$0 表示程序本身

 

 

printf也是一个内部命令,作用和echo相似,按照一定格式显示字符串

[root@localhost ~]# type printf

printf is a shell builtin

[root@localhost ~]# man printf

NAME

printf – format and print data 格式化和打印数据

 

记录不一定非得是一行才成为一条记录,例如:别的形式

[root@localhost ~]# vim file

a:bb;ccc:ddd;

例如该文件中,可以认为“:”分开的为字段,“;”分开的为记录(一行),不是按照回车换行为记录的分隔符,默认记录的分割符是回车换行,也可以是别的字符

 

 

 

awk工作原理

  • 第一步:执行BEGIN{action;… }语句块中的语句

 

  • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

从命令的执行结果来的数据去读取第一行,然后去执行pattern中的action,看是否符合pattern定义,如果符合pattern定义就执行里面的action,不符合就不处理,读取下一行,知道文件处理完

 

  • 第三步:当读至输入流末尾时,执行END{action;…}语句块

 

  • BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个 可选的语句块,比如变量初始化、打印输出表格的表头等语句通常 可以写在BEGIN语句块中

 

  • END语句块在awk从输入流中读取完所有的行之后即被执行,比如 打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

 

  • pattern语句块中的通用命令是最重要的部分,也是可选的。如果 没有提供pattern语句块,则默认执行{ print },即打印每一个读取 到的行,awk读取的每一行都会执行该语句块

 

awk

  • print格式: print item1, item2, … item1表示要打印的字符,可以是普通字符串,也可以是要打印的列
  • 要点:

(1) 逗号分隔符

(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、 变量或awk的表达式

(3) 如省略item,相当于print $0

  • 示例:

awk ‘{print “hello,awk”}’

awk –F:  ‘{print}’  /etc/passwd

awk –F:   ‘{print “wang”}’   /etc/passwd

awk –F: ‘{print $1}’   /etc/passwd awk –F: ‘{print $0}’  /etc/passwd

awk –F: ‘{print $1”\t”$3}’  /etc/passwd tail –3  /etc/fstab |awk ‘{print $2,$4}’

 

例子:

如果pattern忽略不写,就会处理所有行

每读一行显示一行,读进来一看,pattern未定义,符合条件,符合条件就打印

[root@localhost /app]# awk ‘{print “hello”}’ /etc/issue

hello

hello

 

从标准输入读取输入进行打印

[root@localhost /app]# awk ‘{print “hello”}’

a

hello

b

hello

 

awk可以读取标准输入

[root@localhost /app]# cat /etc/issue | awk ‘{print “hello”}’

hello

hello

hello

管道把前一个命令的标准输出作为后一个命令的标准输入

 

[root@localhost /app]# awk ‘{print “hello\nclass27″}’ /etc/centos-release

hello

class27

 

做数字运算,只要是字符串,就需要加引号引起来,数字不需要加引号

[root@localhost /app]# awk ‘{print 2*3}’ /etc/centos-release

6

[root@localhost /app]# awk ‘{print 2^3}’ /etc/centos-release

8

[root@localhost /app]# awk ‘{print 2/3}’ /etc/centos-release

0.666667

 

希望取出特定的字段,awk默认的分隔符是空格

[root@localhost /app]# awk -F “:” ‘{print $1,$3,$7}’ passwd

 

取分区的利用率

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $5}’

8%

1%

4%

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1,$5}’

/dev/sda2 8%

/dev/sda3 1%

/dev/sda1 4%

 

{print $1,$5},$1 和 $5 之间使用“,”,输出时字段的分割符为空格,也可以进行指定,例如:

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1″——“$5}’

/dev/sda2——8%

/dev/sda3——1%

/dev/sda1——4%

 

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1”\t“$5}’

/dev/sda2 8%

/dev/sda3 1%

/dev/sda1 4%

[root@localhost /app]# df | grep /dev/sd | awk ‘{print $1”\n“$5}’

/dev/sda2

8%

/dev/sda3

1%

/dev/sda1

4%

$0打印整行内容

默认不写也是打印整行内容

[root@localhost ~]# df | grep ‘dev/sd’ | awk ‘{ print }’

/dev/sda2       52403200 16332416  36070784  32% /

/dev/sda5       20961280    51048  20910232   1% /app

/dev/sda1        1038336   227464    810872  22% /boot

 

[root@localhost ~]# df | grep ‘dev/sd’ | awk ‘{ print $0 }’

/dev/sda2       52403200 16332416  36070784  32% /

/dev/sda5       20961280    51048  20910232   1% /app

/dev/sda1        1038336   227464    810872  22% /boot

 

 

 

awk变量

  • 变量:内置和自定义变量
  • FS:输入字段分隔符,默认为空白字符

awk -v FS=’:’  ‘{print $1,FS,$3}’ /etc/passwd

awk  –F:   ‘{print $1,$3,$7}’ /etc/passwd

 

awk -v FS=’:’ 等价于 awk -F ‘:’

 

FS:field,称为域、字段、列column、属性

行,称为记录,record

 

  • OFS:输出字段分隔符,默认为空白字符

awk  -v FS=‘:’  -v OFS=‘:’ ‘{print $1,$3,$7}’ /etc/passwd

 

  • RS:输入记录分隔符,指定输入时的换行符

awk -v RS=’ ‘ ‘{print }’ /etc/passwd

  • ORS:输出记录分隔符,输出时用指定符号代替换行符

awk -v RS=’ ‘ -v ORS=’###’‘{print }’ /etc/passwd

  • NF:字段数量

awk  -F: ‘{print NF}’ /etc/fstab,引用内置变量不用$

awk  -F:  ‘{print $(NF-1)}’  /etc/passwd

  • NR:记录号

awk ‘{print NR}’  /etc/fstab ; awk END'{print NR}’  /etc/fstab

 

-v表示给变量赋值,FS是awk自带的变量,字段的分隔符,指定文件输入的分隔符是什么

[root@localhost /app]# awk -F ‘:’ ‘{print $1,$3}’ passwd

[root@localhost /app]# awk -v FS=’:’ ‘{print $1,$3}’ passwd

 

变量的好处是可以在awk中输出时使用

[root@localhost /app]# awk -v FS=’:’ ‘{print $1,FS,$3}’ passwd

root : 0

bin : 1

 

awk还可以使用bash变量,例如调用bash中的变量

[root@localhost /app]# sep=”:”;awk -v FS=”$sep” ‘{print $1,FS,$3}’ passwd

root : 0

bin : 1

-F只能在外面使用bash中的变量,但是里面就无法使用了

[root@localhost ~]# sep=”:”;awk -F “$sep” ‘{print $1,”:”$3}’ passwd

root :0

bin :1

 

 

 

输出分隔符

[root@localhost /app]# awk -v FS=’:’ -v OFS=’+’ ‘{print $1,$3}’ passwd

root+0

bin+1

输入分割符决定字段之间怎么分割进行处理

输出分隔符决定字段之间怎么输出进行显示

 

把一个文件读进来怎么知道怎样算是一条记录?默认回车换行是一条记录

例如:认为一条记录的分割符为‘;’,字段的分隔符默认为空白符

[root@localhost /app]# cat file

aa bb cc;ee

ff oo;xx

yy zz

 

[root@localhost /app]# awk -v RS=”;” ‘{print $2}’ file

bb

ff

yy

 

[root@localhost /app]# cat file

a

b

aa

bb

cc aaa

bb

ccc aaa

以空格作为行的分隔符

[root@localhost /app]# awk -v RS=” ” ‘{ print $1,$2}’ file

a b

aa bb

aaa bb

aaa

以空格作为行的分隔符,所以abc算是一条记录,默认字段的分割符为空白符,回车换行也是空白符,所以a是$1,b是$2,c是$3,所以第一行为a b

所以,记录分别是:

a b c

aa bb cc

aaa bb ccc

aaa

输出的时候一条一条的记录默认是换行分割出来的,输出的时候,记录和记录之间到的默认分割符是回车换行

指定输出的分隔符

[root@localhost ~]# cat f2.txt

a b

aa bb

aaa bb

aaa

指定输出记录的分隔符

[root@localhost ~]# awk -v RS=” ” -v ORS=”—“ ‘{print $1,$2}’ f2.txt

a —b aa—bb aaa—bb aaa—

 

字段数量NF

显示每个行有多少个字段

[root@localhost ~]# awk -F: ‘{print NF}’ /etc/passwd

7

 

输出最后一个字段

[root@localhost ~]# awk -F: ‘{print $NF}’ /etc/passwd

/bin/bash

 

输出倒数第二个字段

[root@localhost ~]# awk -F: ‘{print $(NF-1)}’ /etc/passwd

/root

 

取出远程连接IP

[root@localhost ~]# ss -nt | awk ‘{print $NF}’ | awk -F: ‘{print $1}’

Address

172.18.101.66

 

取出分区利用率

[root@localhost ~]# df | grep ‘/dev/sd’ | awk ‘{print $(NF-1)}’|awk -F% ‘{print $1}’

32

1

22

取http访问日志

[root@localhost /app]# awk ‘{print $1}’ /var/log/httpd/access_log

172.18.101.66

 

NR:记录号,每条记录的编号

[root@localhost /app]# awk ‘{print NR,$0}’ /etc/passwd

1 root:x:0:0:root:/root:/bin/bash

 

空行也算行号

[root@localhost /app]# awk ‘{print NR,$0}’ /etc/fstab

1

2 #

3 # /etc/fstab

 

同时处理多个文件

[root@localhost /app]# awk ‘{print NR,$0}’ /etc/fstab /etc/issue

在第一个文件输出完之后接着输出第二个文件的内容

 

同时处理多个文件,每个文件独立编号

[root@localhost /app]# awk ‘{print FNR,$0}’ /etc/fstab /etc/issue

1

2 #

3 # /etc/fstab

1 \S

2 Kernel \r on an \m

3

 

显示文件名

[root@localhost /app]# awk ‘{print FNR,FILENAME,$0}’ /etc/fstab /etc/issue

1 /etc/fstab

2 /etc/fstab #

3 /etc/fstab # /etc/fstab

1 /etc/issue \S

2 /etc/issue Kernel \r on an \m

3 /etc/issue

 

awk

  • FNR:各文件分别计数,记录号

awk ‘{print FNR}’  /etc/fstab /etc/inittab

  • FILENAME:当前文件名

awk ‘{print FILENAME}’  /etc/fstab

  • ARGC:命令行参数的个数

awk ‘{print ARGC}’  /etc/fstab /etc/inittab

awk ‘BEGIN {print ARGC}’  /etc/fstab /etc/inittab

 

  • ARGV:数组,保存的是命令行所给定的各参数

awk ‘BEGIN {print ARGV[0]}’  /etc/fstab /etc/inittab

awk ‘BEGIN {print ARGV[1]}’  /etc/fstab /etc/inittab

 

命令行参数的个数

[root@localhost ~]# awk ‘{print ARGC}’ /etc/fstab /etc/issue

3

[root@localhost /app]# awk ‘{print ARGV[0]}’ /etc/fstab /etc/issue

awk

[root@localhost /app]# awk ‘{print ARGV[1]}’ /etc/fstab /etc/issue

/etc/fstab

[root@localhost /app]# awk ‘{print ARGV[2]}’ /etc/fstab /etc/issue

/etc/issue

三个参数从0开始编,认为awk也是参数之一

 

 

awk变量

  • 自定义变量(区分字符大小写)

(1) -v var=value

(2) 在program中直接定义

  • 示例:

awk -v test=’hello gawk’ ‘{print test}’ /etc/fstab

awk -v test=’hello gawk’ ‘BEGIN{print test}’

awk ‘BEGIN{test=”hello,gawk”;print test}’

awk –F:‘{sex=“male”;print $1,sex,age;age=18}’ /etc/passwd

cat awkscript  {print script,$1,$2}  awk -F: -f awkscript script=“awk” /etc/passwd

 

自定义变量

# awk -v sep=”:” -F: ‘{print $1sep$3}’ /etc/passwd

root:0

 

分别进行定义

# awk -v uid=”uid” -F: ‘{user=”username”;print user”:”$1,uid”:”$3}’ /etc/passwd

username:root uid:0

 

# awk -v user=”username” -v uid=”uid” -F: ‘{print user”:”$1,uid”:”$3}’ /etc/passwd

username:root uid:0

 

在program中直接定义

# awk -F: ‘{user=”username”;uid=”uid”; print user”:”$1,uid”:”$3}’ /etc/passwd

username:root uid:0

定义在awk程序里面不能使用bash中的变量,在外部定义可以使用bash中的变量

 

# u=”user”; awk -F: -v user=”$u” ‘{uid=”uid”; print user”:”$1,uid”:”$3}’ /etc/passwd

user:root uid:0

 

 

先使用后定义会现第一行不生效的问题

# awk -F: ‘{print user”:”$1,uid”:”$3;user=”user”;uid=”userid”}’ /etc/passwd

:root :0

user:bin userid:1

原因:第一行读取进来进行处理的时候,user和uid还是未定义的状态,但是到第二行的时候,就已经是定义了的状态了。这一行定义的变量将会在下一行起作用。为避免出现问题,建议先声明后使用

 

 

把awk的指定放入文件中

[root@localhost ~]# cat awk.script

{user=”username”;uid=”userid”;print user”:”$1,uid”:”$3}

 

[root@localhost ~]# awk -F: -f awk.script /etc/passwd

username:root userid:0

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/90685

(0)
无言胜千言无言胜千言
上一篇 2017-12-31 19:35
下一篇 2018-01-01 15:38

相关推荐

  • RHEL6.4 yum访问HTTPS源时出错

    在RHEL6.4上安装OpenStack时,使用epel的源,但源是https的,进行安装时,总报下面的错误。     https://repos.fedorapeople.org/repos/openstack/openstack-icehouse/epel-6/repodata/repomd.xml:  …

    Linux干货 2016-02-28
  • 26期全程班-第一周博客作业

    1、描述计算机的组成与功能。 计算机由以下五大单元组成: 一:CPU的算法计算和逻辑判断单元; 二:CPU的控制单元;协调各设备协同工作。 三:内存:RAM(random accace memory)随机读取内存;数据处理的必经路段。 四:输入设备:键盘、鼠标等;负责数据的输入。 五:输出设备:屏幕、终端、文件、硬盘等;负责数据的输出 2、按系列罗列Linu…

    Linux干货 2016-12-30
  • mysql/mariadb基于ssl的主从复制

     当mysql/mariadb跨越互联网进行复制时别人可以窃取到mysql/mariadb的复制信息, 这些信息是明文的, 因此存在不安全性, 这里通过ssl对复制的信息进行加密      1. 创建证书中心 在主服务器上创建证书中心 cd /etc/pki/CA 生成私钥 (umask&…

    Linux干货 2016-12-05
  • centos6开机启动流程以及系统服务配置管理

    内容:   CentOS6 的启动流程   服务管理(chkconfig)   手动制定系统开机服务脚本 一、centos6系统启动流程 综述过程: POST–>BIOS(Boot Sequence)–>MBR(grub,446)–>Kernel–>init…

    Linux干货 2016-09-08
  • shell脚本编程基础

    一.编程基础              程序:指令+数据              程序编程风格:  &n…

    Linux干货 2016-08-12
  • RAID磁盘阵列

    什么是RAID?    RIAD(Redundant Array of Independent Disk,独立冗余磁盘阵列)技术是加州大学伯克利分校1987年提出,最初是为了组合小的廉价磁盘来代替大的昂贵磁盘,同时希望磁盘失效时不会使对数据的访问受损失而开发出一定水平的数据保护技术。RAID就是一种由多块廉价磁盘构成的冗余阵列,在操作系统下是作为一个独立的大…

    Linux干货 2016-12-13