Linux中awk的使用方法详解

在学习awk之前我们应该都学过sed,grep,tr,cut等等命令,这些命令都是为了方便我们对Linux下文本和数据的处理,但是我们会发现很多时候这些命令并不能一下子就完全解决我们的需求,很多时候我们都需要使用管道符结合这些命令来使用,今天我就给大家介绍一个命令awk,他就能很好的解决我们对文本和数据处理的需求,使我们一条命令就解决很多问题。

一、awk命令简介

awk被称为文本处理三剑客之一,其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
所以说awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

二、awk命令格式及选项

语法形式

awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)

常用命令选项

-F fs fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value 赋值一个用户定义变量,将外部变量传递给awk
-f scripfile 从脚本文件中读取awk命令
-m[fr] val 对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

三、awk的原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

第一步:执行BEGIN{ commands }语句块中的语句;
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{ commands }语句块。
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

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

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

四、awk 基本用法

awk的调用有三种方式

1.命令行方式

awk [-F field-separator] 'commands' input-file(s)

其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

2.shell脚本方式

awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中,例如:

awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename

3.将所有的awk命令插入一个单独文件,然后调用

awk -f awk-script-file input-file(s)

其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的命令行方式是一样的。
我们通过几个简单的示例来进一步了解awk的用法

[root@localhost ~]# awk '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
.........................................................................
[root@localhost ~]# echo 123|awk '{print "hello,awk"}'
hello,awk

[root@localhost ~]# awk '{print "hi"}' /etc/passwd
hi
hi
hi
hi
hi
hi
hi
hi
hi
.........................................................................

我们指定/etc/passwd作为输出文件,执行awk时,它就会依次对/etc/passwd中的每一行执行print命令。

awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。如

打印/etc/passwd下所有的用户名

[root@localhost ~]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
adm

........................................................................
打印/etc/passwd下所有的用户名及UID

[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2

........................................................................
以username: XXX  uid: XXX格式输出

[root@localhost ~]# awk -F: '{print "username: " $1 "\t\tuid: "$3}' /etc/passwd
username: root   uid: 0
username: bin    uid: 1
username: daemon    uid: 2
........................................................................

五、awk内置变量

变量 描述
\$n 当前记录的第n个字段,字段间由FS分隔
\$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 各文件分别计数的行号
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认值是%.6g)
OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS 输出记录分隔符(默认值是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)

示例

[root@localhost ~]# echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line No:3, No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7

使用print $NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段,其他以此类推:

[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $NF}'
f3
f5
[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $(NF-1)}'
f2
f4

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

[root@localhost ~]# awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin

统计/etc/passwd文件中的命令行参数ARGC,文件行号FNR,字段分隔符FS,一条记录的字段数目NF,已经读出的记录数(默认是行号)NR

[root@localhost ~]# awk -F: 'BEGIN{printf "%4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR}' /etc/passwd
FILENAME ARGC FNR  FS  NF  NR
---------------------------------------------
/etc/passwd  2  1  :  7  1
/etc/passwd  2  2  :  7  2
/etc/passwd  2  3  :  7  3

六、awk高级用法

1.awk赋值运算

赋值语句运算符:= += -= *= /= %= ^= **=

例如:a+=5;等价于a=a+5

[root@localhost ~]# awk 'BEGIN{a=5;a+=5;print a}'
10

2.awk正则运算
输出包含有root的行,并打印用户名和UID及原行内容

[root@localhost ~]# awk -F: '/root/ {print $1,$3,$0}' /etc/passwd
root 0 root:x:0:0:root:/root:/bin/bash
operator 11 operator:x:11:0:operator:/root:/sbin/nologin

我们发现找到了两行,如果我们想找root开头的行就要这样写:awk -F: '/^root/' /etc/passwd

3.awk三目运算

[root@localhost ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
ok
[root@localhost ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'
err

三目运算其实就是一个判断运算,如果为真则输出?后的内容,如果为假则输出:后的内容

4.awk的循环运用

if语句运用

[root@localhost ~]# awk 'BEGIN{ test=100;if(test>90){ print "vear good";} else{print "no pass";}}'
vear good

每条命令后用;结尾
while循环运用
计算从1累加到100的值

[root@localhost ~]# awk 'BEGIN{test=100;num=0;while(i<=test){num+=i; i++;}print num;}'
5050
for循环的运用
[root@localhost ~]# awk 'BEGIN{test=0;for(i=0;i<=100;i++){test+=i;}print test;}'
5050
do循环的运用
[root@localhost ~]# awk 'BEGIN{test=0;i=0;do{test+=i;i++}while(i<=100)print test;}'
5050

5.awk的数组运用

数组是awk的灵魂,处理文本中最不能少的就是它的数组处理。因为数组索引(下标)可以是数字和字符串在awk中数组叫做关联数组(associative arrays)。awk 中的数组不必提前声明,也不必声明大小。数组元素用0或空字符串来初始化,这根据上下文而定。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
显示/etc/passwd的账户

awk -F: 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 bin
2 daemon
3 adm
4 lp
5 sync
........................................................................

6.awk字符串函数的运用

函数名 描述
sub 匹配记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配的 时候
sub (regular expression, substitution string):
sub (regular expression, substitution string, target string)

实例:

     awk '{ sub(/test/, "mytest"); print }' testfile
     awk '{ sub(/test/, "mytest"); $1}; print }' testfile

第一个例子在整个记录中匹配,替换只发生在第一次匹配发生的时候。如要在整个文件中进行匹配需要用到gsub

第二个例子在整个记录的第一个域中进行匹配,替换只发生在第一次匹配发生的时候。
gsub 整个文档中进行匹配
gsub (regular expression, substitution string)
gsub (regular expression, substitution string, target string)

实例:

     awk '{ gsub(/test/, "mytest"); print }' testfile
     awk '{ gsub(/test/, "mytest" , $1) }; print }' testfile

第一个例子在整个文档中匹配test,匹配的都被替换成mytest。

第二个例子在整个文档的第一个域中匹配,所有匹配的都被替换成mytest。
index 返回子字符串第一次被匹配的位置,偏移量从位置1开始
index(string, substring)

实例:

awk '{ print index("test", "mytest") }' testfile

实例返回test在mytest的位置,结果应该是3。
substr 返回从位置1开始的子字符串,如果指定长度超过实际长度,就返回整个字符串
substr( string, starting position )
substr( string, starting position, length of string )

实例:

         awk '{ print substr( "hello world", 7,11 ) }'

上例截取了world子字符串。
split 可按给定的分隔符把字符串分割为一个数组。如果分隔符没提供,则按当前FS值进行分割
split( string, array, field separator )
split( string, array )

实例:

awk '{ split( "20:18:00", time, ":" ); print time[2] }'

上例把时间按冒号分割到time数组内,并显示第二个数组元素18。
length 返回记录的字符数
length( string )
length

实例:

     awk '{ print length( "test" ) }'
     awk '{ print length }' testfile

第一个实例返回test字符串的长度。

第二个实例返回testfile文件中第条记录的字符数。
match 返回在字符串中正则表达式位置的索引,如果找不到指定的正则表达式则返回0。match函数会设置内建变量RSTART为字符串中子字符串的开始位 置,RLENGTH为到子字符串末尾的字符个数。substr可利于这些变量来截取字符串

match( string, regular expression )

实例:

     awk '{start=match("this is a test",/[a-z]+$/); print start}'
     awk '{start=match("this is a test",/[a-z]+$/); print start, RSTART, RLENGTH }'

第一个实例打印以连续小写字符结尾的开始位置,这里是11。

第二个实例还打印RSTART和RLENGTH变量,这里是11(start),11(RSTART),4(RLENGTH)。
toupper和tolower 可用于字符串大小间的转换,该功能只在gawk中有效

toupper( string )
tolower( string )

实例:

awk '{ print toupper("test"), tolower("TEST") }'

(0)

相关推荐

  • linux awk时间计算脚本及awk命令详解

    在linux如果计划时间是个麻烦事, 用awk脚本如下 BEGIN {FS=":";OFS=":"} {total_seconds=total_seconds+$3} total_seconds>=60 {total_seconds=total_sconds-60 $2=$2+1 } {total_minutes=total_minutes+$2 $2=$2+1 } {total_minutes=total_minutes+$2} total_minutes&

  • linux shell awk获得外部变量(变量传值)简介

    AWK 提供了极其强大的功能: 可以进行正则表达式的匹配 样式装入 流控制 数学运算符 进程控制语句 内置的变量和函数 可以把awk看作一门完全的程序设计语言,它处理文本的速度是快得惊人的.现在很多基于shell 日志分析工具都可以用它完成.设计简单,速度表现很好. 涉及到以上六个方面内容,我会在以后文章中加以介绍. 这次主要说下,怎么样把外部变量传入到awk执行语句中. 一.基础: awk [ -F re] [parameter...] ['pattern {action}' ] [-f pr

  • Linux awk将文件某列按照逗号分隔的例子

    概述 当我们在处理线上故障的时候,经常会从数据库表查询出某个列. select product_id from order where user_id = 111; 查询出来的结果形式如下: 1 2 3 4 5 这个时候,我们通常会以 product_id in (1,2,3,4,5) 的形式去查找商品表,找出商品的详细信息.那么如何得到这个(1,2,3,4,5)呢.一种简单的做法就是利用awk. cat temp.txt | awk 'BEGIN{ORS=","} {print $0

  • linux awk高级应用实例

    今天看到unix shell 范例精解上有道awk的题目 做了以后拿来和大家分享下 处理前的文档: Mike Harrington:(510) 548-1278:250:100:175  Christian Dobbins:(408) 538-2358:155:90:201  Susan Dalsass:(206) 654-6279:250:60:50  Archie McNichol:(206) 548-1348:250:100:175  Jody Savage:(206) 548-1278:

  • Linux中 sed 和 awk的用法详解

    sed用法: sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法 sed命令行格式为: sed [-nefri] 'command' 输入文本 常用选项: -n∶使用安静(silent)模式.在一般 sed 的用法中,所有来自 STDIN的资料一般都会被列出到萤幕上.但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来. -e∶直接在指令列模式上进行 sed 的

  • 一天一个shell命令 linux文本内容操作系列-awk命令详解

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理. awk有3个不同版本: awk.nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本. awk其名称得自于它的创始人 Alfred Aho .Peter Weinberger 和 Brian Kernighan 姓氏的首个字母.实际上 AWK

  • linux之awk命令的用法

    先来一个例子:文件a,统计文件a的第一列中是浮点数的行的浮点数的平均值.用awk来实现只需要一句话就可以搞定$cat a1.021 331#.ll   442.53 6ss    7 awk 'BEGIN{total = 0;len = 0} {if($1~/^[0-9]+\.[0-9]*/){total += $1; len++}} END{print total/len}' a(分析:$1~/^[0-9]+\.[0-9]*/表示$1与"/ /"里面的正则表达式进行匹配,若匹配,则t

  • Linux里awk中split函数的用法小结

    The awk function split(s,a,sep) splits a string s into an awk array a using the delimiter sep. set time = 12:34:56set hr = `echo $time | awk '{split($0,a,":" ); print a[1]}'` # = 12set sec = `echo $time | awk '{split($0,a,":" ); print

  • linux正则表达式awk详解

    awk和sed一样是流式编辑器,它也是针对文档中的行来操作的,一行一行的去执行.awk比sed更加强大,它能做到sed能做到的,同样也能做到sed不能做到的.awk常用来分段: awk不用加任何参数就可以实现 + ? * .  | 这些特殊符号: 1.截取文档中的某个段 [root@yonglinux ~]# head -n2 passwd |awk -F: '{print $1}' root bin [root@yonglinux ~]# head -n2 passwd |awk -F: '{

  • Linux中awk的使用方法详解

    在学习awk之前我们应该都学过sed,grep,tr,cut等等命令,这些命令都是为了方便我们对Linux下文本和数据的处理,但是我们会发现很多时候这些命令并不能一下子就完全解决我们的需求,很多时候我们都需要使用管道符结合这些命令来使用,今天我就给大家介绍一个命令awk,他就能很好的解决我们对文本和数据处理的需求,使我们一条命令就解决很多问题. 一.awk命令简介 awk被称为文本处理三剑客之一,其名称得自于它的创始人 Alfred Aho .Peter Weinberger 和 Brian K

  • Linux Docker安装wordpress的方法详解教程

    安装mysql服务 下载mysql镜像: docker pull mysql 创建mysql容器并后台运行,指定数据库密码是123456.-e指定环境变量. docker run --name mysql_db -e MYSQL_ROOT_PASSWORD=123456 -d mysql 使用官方的wordpress wordpress镜像daocloud.io: docker pull daocloud.io/daocloud/dao-wordpress:latest 拉取镜像前请先登录: d

  • Linux中的内核链表实例详解

    Linux中的内核链表实例详解 链表中一般都要进行初始化.插入.删除.显示.释放链表,寻找节点这几个操作,下面我对这几个操作进行简单的介绍,因为我的能力不足,可能有些东西理解的不够深入,造成一定的错误,请各位博友指出. A.Linux内核链表中的几个主要函数(下面是内核中的源码拿出来给大家分析一下) 1)初始化: #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0)

  • C++中正则表达式的使用方法详解

    目录 介绍 1. C++ 中的正则表达式 (Regex) 1.1 范围规范 1.2 重复模式 2. C++正则表达式的例子 3. C++正则表达式中使用的函数模板 3.1 regex_match() 3.2 regex_search() 3.3 regex_replace() 4.C++输入验证 5.总结 介绍 C++ 正则表达式教程解释了 C++ 中正则表达式的工作,包括正则表达式匹配.搜索.替换.输入验证和标记化的功能. 几乎所有的编程语言都支持正则表达式. C++ 从 C++11 开始直接

  • python编程之requests在网络请求中添加cookies参数方法详解

    哎,好久没有学习爬虫了,现在想要重新拾起来.发现之前学习爬虫有些粗糙,竟然连requests中添加cookies都没有掌握,惭愧.废话不宜多,直接上内容. 我们平时使用requests获取网络内容很简单,几行代码搞定了,例如: import requests res=requests.get("https://cloud.flyme.cn/browser/index.jsp") print res.content 你没有看错,真的只有三行代码.但是简单归简单,问题还是不少的. 首先,这

  • Android通过json向MySQL中读写数据的方法详解【读取篇】

    本文实例讲述了Android通过json向MySQL中读取数据的方法.分享给大家供大家参考,具体如下: 首先 要定义几个解析json的方法parseJsonMulti,代码如下: private void parseJsonMulti(String strResult) { try { Log.v("strResult11","strResult11="+strResult); int index=strResult.indexOf("[");

  • java 中enum的使用方法详解

    java 中enum的使用方法详解 enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中. 下面是我在使用 enum 过程中的一些经验和总结. 原始的接口定义常量 public interface IConstants { String MON = "Mon"; String TUE = "Tue"; String WED = "Wed"; String THU = "Thu

  • Android 中RxPermissions 的使用方法详解

    Android 中RxPermissions 的使用方法详解 以请求拍照.读取位置权限为例 module的build.gradle: compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar' compile 'io.reactivex.rxjava2:rxjava:2.0.5' AndroidManifest.xml: <uses-permission android:name="android.permission.AC

  • Android中XUtils3框架使用方法详解(一)

    xUtils简介 xUtils 包含了很多实用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响... xUitls 最低兼容android 2.2 (api level 8) 今天给大家带来XUtils3的基本介绍,本文章的案例都是基于XUtils3的API语法进行的演示.相信大家对这个框架也都了解过, 下面简单介绍下XUtils3的一些基本知识. XUtils3一共有4大功能:注解模块,网络

  • Android 中Context的使用方法详解

    Android 中Context的使用方法详解 概要: Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄.很多方法需要通过 Context才能识别调用者的实例:比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的实例为Activity,而到了一个button的onClick(View view)等方法时,我们用t

随机推荐