博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
awk脚本语言编程指南
阅读量:7223 次
发布时间:2019-06-29

本文共 23873 字,大约阅读时间需要 79 分钟。

安装AWK

# 使用yum安装yum install gawk# 安装后检查是否安装okwhich awk## 一般输出安装路径是在: /bin/awk复制代码

AWK 起步示例

假设存在一个文件 emp.data,其中包含员工的姓名、薪资(美元/小时)以及小时数,一个员工一行数据,其内容如下:

Beth	4.00	0Dan	3.75	0kathy	4.00	10Mark	5.00	20Mary	5.50	22Susie	4.25	18复制代码

如果想打印出 工作时长超过0小时的员工姓名和工资(薪资乘以时间),以下命令可以完成:

awk '$3>0 {print $1, $2*$3}'  emp.data复制代码

得到如下输出:

kathy 40Mark 100Mary 121Susie 76.5复制代码

该命令告诉系统执行括号内的awk程序,从输入文件 emp.data 获取所需要的数据。引号内的部分是个完整的awk程序,包含单个 模式-动作 语句。模式 $3>0 用于匹配第三列大于0的输入行,动作: {print $1, $2*$3} 打印每个匹配行的第一个字段、第二个字段与第三个字段的乘积。

还可以打印没有工作过的员工姓名:

awk '$3==0 {print $1}'  emp.data复制代码

将会输出:

BethDan复制代码

AWK程序的结构

回过头来看一下上述命令。引号之间的部分是awk编程语言写就的程序。 每个awk程序都是 一个或多个 模式-动作 语句的序列:

pattern {pattern} pattern {pattern} ...

awk 的基本操作是一行一行的扫描输入,搜索匹配任意程序中模式的行。 词语“匹配”的准确意义是视具体的模式而言,对于模式 $3>0 来说,意思是“条件为真”。 每个模式依次测试每个输入行。对于匹配到行的模式,其对应的动作(也许包含多步)得到执行,然后读取下一行并继续匹配,直到所有的输入读取完毕。

模式 动作
$3==0 {print $1}

模式-动作 语句中的 模式或动作(但不是两者同时省略)都可以省略。如果某个模式没有动作,例如:

$3==0

那么模式匹配到的每一行都会被打出来。输出如下:

Beth    4.00    0Dan     3.75    0复制代码

如果是没有动作的模式,例如: {print $1} 则会打印第一列,输出如下:

BethDankathyMarkMarySusie复制代码

由于模式和动作两者任一都是可选的,所以需要使用大括号包围动作用以区分其他模式。

执行 awk 程序

执行awk程序有多种,可以输入如下形式的命令行: awk 'program codes' inputfiles 从而在每个指定的输入文件上执行这个program。例如: awk '$3==0 {print $1}' file1 file2 打印 file1 和 file2 文件中第三列为0的每一行的第一个字段。

也可以省略命令行中的输入文件,仅仅输入: awk 'program codes' 在这种情况下,awk 将会应用于你在终端接着输入的任意数据行,直到你输入一个文件结束信号(Unix系统上为control-d)。示例:

awk '$3>0 {print $1}'Mary 20 1000   #输入该行回车Mary  # 计算机输出,匹配到了信息Belly 30 3000  #继续输入改行Belly #计算机输出复制代码

注意事项: 命令行中的程序是用单引号包围着的。这会防止shell解释程序中$这样的字符,也允许程序的长度超过一行。 当程序比较长的时候,可以将程序写入到一个文件,以下命令行: awk -f programfile optional list of input files

其中 选项指示 awk 从指定文件中获取程序。可以使用任意文件名替换 programfile。

awk 的错误提示

如果你的 awk 程序存在错误, awk 会给你一些诊断信息。例如,如果你打错了大括号,如下所示:

awk '$3==0 [print $1}' emp.data 会提示如下错误:

awk: $3==0 [print $1}awk:       ^ syntax errorawk: $3==0 [print $1}awk:                ^ syntax error复制代码

简单输出

awk中仅仅只有两种类型 数值字符 构成的字符串。通常情况下,一个字段是一个不包含任何空格或制表符的连续字符序列。 当前输入的 行中的第一个字段被称作 $1,第二个是 $2,以此类推。 整个行的内容被定义为 $0。 每一行的字段数量可以不同。

大都数情况下,我们仅仅只是打印出其中每一行的某些字段,或者也还需要做一些计算。

打印每一行

如果一个动作没有任何模式,这个动作针对所有输入的行进行操作。 print 语句用来打印(输出)当前输入的行。 所以 {print} 等效于 {print $0}

打印特定行

{print $1,$3} 将输出:

Beth 0Dan 0kathy 10Mark 20Mary 22Susie 18复制代码

在 print 语句中被逗号分隔的表达式,在默认情况下他们将会用一个空格分割来输出。 每一行print生成的内容都会以一个换行符作为结束。但这些默认行为都可以自定义。

NF,字段数量

AWK 会对当前输入的行有多少字段进行计数,并且将当前行的字段数量存储在一个内建的称为 NF 的变量中。因此 {print NF,$1,$NF} 会打印出 每一行的字段数量、第一个字段的值、最后一个字段的值。 输出:

3 Beth 03 Dan 03 kathy 103 Mark 203 Mary 223 Susie 18复制代码

打印行号

awk 提供了另一个内建变量, NR。他存储了当前已经读取了多少行的计数。可以使用 NR和$0给emp.data的每一行加上行号: {print NR,$0} 输出如下:

1 Beth  4.00    02 Dan   3.75    03 kathy 4.00    104 Mark  5.00    205 Mary  5.50    226 Susie 4.25    18复制代码

在输出中添加内容

还可以在字段中间或者计算的值中间打印输出想要的内容: {print "total pay for", $1, "is", $2*$3} 输出如下:

total pay for Beth is 0total pay for Dan is 0total pay for kathy is 40total pay for Mark is 100total pay for Mary is 121total pay for Susie is 76.5复制代码

高级输出

print 语句可用于快速而简单的输出。若要严格按照你所想的格式化输出,则需要使用 printf 语句。

字段排队

printf 语句格式如下:

printf(format, value1, value2, ..., valueN)

其中 format 是字符串,包含要逐字打印的文本,穿插在 format 之后的每个值该如何打印的规格。一个规格是一个 % 符,后面跟着一些字符,用来控制一个 value 的格式。因此,有过少个 value 要打印,在 fromat 中就要有多少个 % 规格。 打印每个员工的总薪酬: {printf("total pay for %s is $%.2f\n", $1, $2*$3)} 输出如下:

awk '{printf("total pay for %s is $%.2f\n", $1, $2*$3)}'  emp.datatotal pay for Beth is $0.00total pay for Dan is $0.00total pay for kathy is $40.00total pay for Mark is $100.00total pay for Mary is $121.00total pay for Susie is $76.50复制代码

排序输出

以薪酬递增的方式输出每一行:

awk '{printf("%6.2f %s\n", $2*$3, $0)}' emp.data | sort

将awk的输出通过管道传给 **sort **命令,输出如下:

0.00  Beth    4.00    0  0.00  Dan     3.75    0100.00  Mark    5.00    20121.00  Mary    5.50    22 40.00  kathy   4.00    10 76.50  Susie   4.25    18复制代码

选择

awk 的模式适用于为进一步的处理从输入中选择相关的数据行。由于不带动作的模式会打印所有匹配的行,所以很多awk程序仅仅包含一个模式。本节将给出一些有用的模式示例。

通过对比选择

使用一个对比模式来选择每小时赚5美元或更多的员工记录,亦即第二个字段大于等于5的行: $2>=5

awk '$2>=5'  emp.dataMark    5.00    20Mary    5.50    22复制代码

通过计算选择

awk '$2*$3>50 {printf("$%.2f for %s\n", $2*$3, $1)}'  emp.data$100.00 for Mark$121.00 for Mary$76.50 for Susie复制代码

通过文本内容选择

除了数值测试,还可以选择包含特定单词或短语的输入行。这个程序会打印所有第一个字段为 Susie 的行:

$1=="Susie"

操作符 == 用于测试相等性。 也可以使用正则表达式的模式查找包含任意任意字母组合,单词或短语的文本。如以下可以匹配到任意位置包含Susie的行: /Susie/

awk '/Susie/'  emp.dataSusie   4.25    18复制代码

模式组合

可以使用括号和逻辑操作符号与&&、或||,以及 非! 对模式进行组合。 $2>=4||$3>=20 会打印第二个字段大于等于4或者第三个字段大于等于20的行:

awk '$2>=4||$3>=20'  emp.dataBeth    4.00    0kathy   4.00    10Mark    5.00    20Mary    5.50    22Susie   4.25    18复制代码

BEGIN 与 END

特殊模式 BEGIN 用于匹配第一个输入文件的第一行之前的位置。END 则用于匹配处理过的最后一个文件的最后一行的位置。

这个程序使用 BEGIN 来输出一个标题:

BEGIN {
print "Name RATE HOURS"; print ""} {
print}复制代码
awk 'BEGIN {print "Name RATE HOURS"; print ""}{print}' emp.data## 输出如下:Name RATE HOURSBeth    4.00    0Dan     3.75    0kathy   4.00    10Mark    5.00    20Mary    5.50    22Susie   4.25    18复制代码

注意事项:

  • awk 可以在一行上放多个语句,步过要使用分号;进行分隔。

  • 普通的 print 是打印当前输入行, print "" 则会打印一个空行。

AWK 工作流图

AWK 是按一行一行地读取输入的。

  • 1.首先执行 BEGIN
  • 2.从输入中读取一行
  • 3.在这次读取的这一行中执行 AWK 命令
  • 4.如果文件还没有读取完毕,则重复步骤2、3
  • 5.执行 END 块中的 awk 命令

使用 AWK 进行计算

一个动作就是一个以新行或者分号分隔的语句序列。

计数
$3 > 15 {emp = emp + 1}END {
print emp, "employees worked more than 15 hours"}复制代码
awk '$3 > 15 {emp = emp + 1}> END {
print emp, "employees worked more than 15 hours"}' emp.data## 输出结果:3 employees worked more than 15 hours复制代码

用作数字的 awk 变量的默认初始值为0, 所以不需要初始化 emp。创建一个变量emp初始值为0,如果读入的那一行的第三个字段大于15,则emp在自身值的基础上自增1,读完最后一行后输出存在多少个员工工作时长超过15个小时的语句。

求和与平均值

为计算员工数目,可以使用内置变量 NR,保存了当前位置读取的行数;在所有输入的结尾它的值就是所读行的总行数。

END {print NR, "employees"}

awk 'END {print NR, "employees"}'  emp.data## 输出结果为:6 employees复制代码

如下是一个使用 NR 来计算薪酬均值的程序:

awk '{pay = pay + $2*$3}> END {
print NR, "employees"> print "total pay is", pay> print "average pay is", pay/NR> }' emp.data## 输出结果为:6 employeestotal pay is 337.5average pay is 56.25复制代码

处理文本

awk 的优势之一是能像大多数语言处理数字一样方便地处理字符串。 awk 可以保存数字也可以保存字符。找出时薪最高的员工:

$2 > maxrate { maxrate = $2; maxemp = $1 }END { print "highest hourly rate:", maxrate, "for", maxemp }复制代码
awk '$2 > maxrate { maxrate = $2; maxemp = $1 }> END { print "highest hourly rate:", maxrate, "for", maxemp }' emp.data## 输出结果为:highest hourly rate: 5.50 for Mary复制代码
awk '{names = names $1 " "}                    END {print names}' emp.data## 输出结果:Beth Dan kathy Mark Mary Susie 复制代码

打印最后一个输入行

虽然在 END 动作中 NR 还保留着它的值, 但 $0 没有。

{last = $0}END {
print last}复制代码
awk '> {last = $0}> END {
print last}' emp.data## 输出结果:Susie 4.25 18复制代码

AWK 内置函数

前面已经看到 awk 内置变量用来保存某些频繁使用的数量, NF 表示所在行的总列数, NR 表示当前是第多少行... 还有内置函数用来计算其他有用的数值。除了 平方根、对数、随机数此类的算术函数外,还有操作文本的函数。其中之一是 length 用于计算一个字符串的长度。

awk '{print $1, length($1)}'  emp.data## 输出结果:Beth 4Dan 3kathy 5Mark 4Mary 4Susie 5复制代码

行、单词以及字符的计数

使用 length、NF、NR来统计输入中行、单词以及字符的数量。为了简便,将每个字段看作一个单词。

awk ' { nc = nc + length($0) + 1>       nw = nw + NF>     }> END { print NR, "lines,", nw, "words,", nc, "characters" }' emp.data## 输出结果为:6 lines, 18 words, 82 characters复制代码

因为 $0 不会包含行末的换行符,所以另外加了个1。

AWK 控制语句

awk 为选择提供了一个 if-else 语句, 以及为循环提供了几个语句,它们仅在动作中使用。

if-else 语句

如下是一个计算时薪超过6美元的员工总薪酬与平均薪酬。它使用一个 if 来防范零除问题。

$2 > 6 { n = n+1; pay = pay + $2*$3 }END {    if(n > 0)        print n, "employees, total pay is", pay,               "average pay is", pay/n    else        print "no employees are paid more than $6/hour"        }复制代码
awk '$2 > 6 { n = n+1; pay = pay + $2*$3 }> END {
> if(n > 0)> print n, "employees, total pay is", pay,> "average pay is", pay/n> else> print "no employees are paid more than $6/hour"> > }' emp.data## 输出结果为:no employees are paid more than $6/hour复制代码

注意事项: 我们可以使用一个逗号将一个长语句截断为多行来书写.

while 语句
{    i = 1    while ( i <=3 ){        # while 循环体(这一行是注释内容)        printf("\t%.2f\n", $1*(1+$2)^i)        i = i + 1    }}复制代码

while 后面是圆括号,里面是布尔表达式。 循环体是条件后大括号包围的语句。 ^ 是指数操作符。 # 后面是注释。

演示1000美元,利率为6%与12%,5年的复利分别是如何增长的:

awk '> {>     i = 1>     while ( i <=5 ){>         # while 循环体(这一行是注释内容)>         printf("\t%.2f\n", $1*(1+$2)^i)>         i = i + 1>     }> }> ' 1000 .06 5        1060.00        1123.60        1191.02        1262.48        1338.231000 .12 5        1120.00        1254.40        1404.93        1573.52        1762.34复制代码
for 语句

使用for循环实现上述例子:

awk '> {
> for( i = 1; i <= $3; i = i+1 ){
> printf("\t%.2f\n", $1*(1+$2)^i)> }> }> '1000 .06 5 1060.00 1123.60 1191.02 1262.48 1338.231000 .12 5 1120.00 1254.40 1404.93 1573.52 1762.34复制代码

数组

awk 为存储一组相关的值提供了数组,虽然数组给予了awk很强的能力,但是在这里我们仅仅展示一个简单的例子。 第一个动作将输入行存为数组 line 的连续元素; 第一行放在line[1],第二行放在line[2]。 END 动作使用一个while语句从后往前打印数组中的输入行:

# 反转-按行逆序打印输入{line[NR] = $0}END {        i = NR        while(i > 0){            print line[i]            i = i-1        }}复制代码
awk '> {line[NR] = $0}> > END {>         i = NR>         while(i > 0){>             print line[i]>             i = i-1>         }> }' emp.data# 输出结果为:Susie   4.25    18Mary    5.50    22Mark    5.00    20kathy   4.00    10Dan     3.75    0Beth    4.00    0复制代码

--dump-variables 操作查看全局变量

-dump-variables[=file] 操作可以打印全局变量到文件中,默认是“awkvars.out”文件。

awk --dump-variables ''# 查看文件awkvars.out cat awkvars.out ARGC: number (1)ARGIND: number (0)ARGV: array, 1 elementsBINMODE: number (0)CONVFMT: string ("%.6g")ERRNO: number (0)FIELDWIDTHS: string ("")FILENAME: string ("")FNR: number (0)FS: string (" ")IGNORECASE: number (0)LINT: number (0)NF: number (0)NR: number (0)OFMT: string ("%.6g")OFS: string (" ")ORS: string ("\n")RLENGTH: number (0)RS: string ("\n")RSTART: number (0)RT: string ("")SUBSEP: string ("\034")TEXTDOMAIN: string ("messages")复制代码

--help 操作可以寻得帮助

awk --help# 输出信息如下:Usage: awk [POSIX or GNU style options] -f progfile [--] file ...Usage: awk [POSIX or GNU style options] [--] 'program' file ...POSIX options:          GNU long options:        -f progfile             --file=progfile        -F fs                   --field-separator=fs        -v var=val              --assign=var=val        -m[fr] val        -O                      --optimize        -W compat               --compat        -W copyleft             --copyleft        -W copyright            --copyright        -W dump-variables[=file]        --dump-variables[=file]        -W exec=file            --exec=file        -W gen-po               --gen-po        -W help                 --help        -W lint[=fatal]         --lint[=fatal]        -W lint-old             --lint-old        -W non-decimal-data     --non-decimal-data        -W profile[=file]       --profile[=file]        -W posix                --posix        -W re-interval          --re-interval        -W source=program-text  --source=program-text        -W traditional          --traditional        -W usage                --usage        -W use-lc-numeric       --use-lc-numeric        -W version              --versionTo report bugs, see node `Bugs' in `gawk.info', which issection `Reporting Problems and Bugs' in the printed version.gawk is a pattern scanning and processing language.By default it reads standard input and writes standard output.Examples:        gawk '{ sum += $1 }; END { print sum }' file        gawk -F: '{ print $1 }' /etc/passwd复制代码

--version 查看版本信息

awk --version# 输出结果如下:GNU Awk 3.1.7Copyright (C) 1989, 1991-2009 Free Software Foundation.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program. If not, see http://www.gnu.org/licenses/.复制代码

-v 操作

-v 操作允许给一个变量分配值。允许在程序执行之前分配。

awk -v name=LFF 'BEGIN {printf("username=%s\n", name)}'# 输出结果为:username=LFF复制代码

--lint 操作提示信息

--lint 操作允许输出检查信息,比如当参数提供错误,会将警告信息当作错误。

awk --lint '' /bin/ls# 输出结果为:awk: warning: empty program text on command lineawk: warning: source file does not end in newlineawk: warning: no program text at all!复制代码

正则匹配

匹配输入行中包含字符a的行,全部输出。

awk '/a/ {print $0}'  emp.data# 输出结果为:Dan     3.75    0kathy   4.00    10Mark    5.00    20Mary    5.50    22复制代码

打印输入行中包含字符a的行数:

awk '/a/ {++cnt} END {print "匹配的行数为:", cnt}' emp.data# 输出结果为:匹配的行数为: 4复制代码

内置变量

ARGC :命令行中提供的参数个数

shell awk 'BEGIN {print "Arguments =", ARGC}' One Two Three Four Arguments = 5

ARGV 表示命令行入参构成的数组,索引是 0~ARGC-1
awk 'BEGIN { >    for (i = 0; i < ARGC - 1; ++i) { >       printf "ARGV[%d] = %s\n", i, ARGV[i] >    } > }' one two three four# 输出结果为:ARGV[0] = awkARGV[1] = oneARGV[2] = twoARGV[3] = three复制代码
CONVFMT

表示数字的转换格式。默认值是 %.6g

awk 'BEGIN { print "Conversion Format =", CONVFMT }'#输出:Conversion Format = %.6g复制代码
ENVIRON 环境变量
awk 'BEGIN { print ENVIRON["USER"] }'# 输出当前用户deploy复制代码

我们可以借助env命令查看linux服务器上的全部环境变量:

env# 查看当前服务器上的所有环境变量HOSTNAME=sz-local3TERM=vt100SHELL=/bin/bashHISTSIZE=1000SSH_CLIENT=10.89.4.224 53217 22QTDIR=/usr/lib64/qt-3.3OLDPWD=/data/appQTINC=/usr/lib64/qt-3.3/includeSSH_TTY=/dev/pts/0GREP_OPTTIONS=--color=alwaysUSER=deployLS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:MAIL=/var/spool/mail/deployPATH=/usr/lib/jdk1.7.0_76/bin:/usr/lib64/qt-3.3/bin:/data/app/node-v4.2.4-linux-x64/bin:/usr/lib/jdk1.7.0_76/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/deploy/binPWD=/data/app/lffJAVA_HOME=/usr/lib/jdk1.7.0_76LANG=en_US.UTF-8HISTCONTROL=ignoredupsSHLVL=1HOME=/home/deployLOGNAME=deployQTLIB=/usr/lib64/qt-3.3/libCVS_RSH=sshCLASSPATH=/usr/lib/jdk1.7.0_76/lib:/usr/lib/jdk1.7.0_76/lib:SSH_CONNECTION=10.89.4.224 53217 10.193.1.27 22LESSOPEN=||/usr/bin/lesspipe.sh %sG_BROKEN_FILENAMES=1_=/bin/env复制代码
FILENAME 表示当前文件
awk 'END {print FILENAME}' emp.data# 输出结果为:emp.data复制代码
FS 表示文件分隔符

FS 表示文件分割符,默认是空白字符。也可以使用 -F 命令行变更。

awk 'BEGIN {print "FS = " FS}' | cat -vte# 输出结果为:FS =  $复制代码
NF 表示当前行的字段(列数)
NR 表示当前读到的行数
RLENGTH

表示匹配函数 match 到的字符串的长度。

awk 'BEGIN {       if(match("One Two Three", "re")){          print RLENGTH       }}'# 匹配到了Three中的re,输出结果为:2复制代码
RSTART 表示第一个match函数匹配到的字符串中的位置
awk 'BEGIN {       if(match("One Two Three There", "re")){          print RSTART        }}'# 从O开始,到Three的r,位置处于11,输出结果为:11复制代码
$0 表示全部的输入记录
$n 表示第n列(第n个字段),以文件分隔符分隔,默认是空白字符。
ARGIND 表示当前处理的 ARGV 的索引值
PROCINFO 表示进程相关信息
awk 'BEGIN {print PROCINFO["pid"]}'5142复制代码

运算符操作

自增符操作
awk 'BEGIN {print ++a}'# 先自增,输出结果为:1# 后自增,输出结果为:awk 'BEGIN {print a++}'0复制代码
自减符操作
awk 'BEGIN {print --a}'-1awk 'BEGIN {print a--}'0复制代码
+=、 -=、 *=、/=、%=、 ^=、**=操作
awk 'BEGIN {print cnt+=10; print cnt}'1010awk 'BEGIN {cnt=10 ;print cnt*=10; print cnt}'100100awk 'BEGIN {cnt=10 ;print cnt-=10; print cnt}'00awk 'BEGIN {cnt=10 ;print cnt/=10; print cnt}'11awk 'BEGIN {cnt=10 ;print cnt%=10; print cnt}'00awk 'BEGIN {cnt=10 ;print cnt^=10; print cnt}'1000000000010000000000awk 'BEGIN {cnt=10 ;print cnt**=10; print cnt}'1000000000010000000000复制代码
关系运算符
  • ==
  • !=
  • <
  • <=
  • >
  • >=
逻辑运算符
  • &&
  • ||
  • !
三目运算符
  • ? :
字符串连接符

空白字符是字符串连接符

awk 'BEGIN {a="hello, "; b="world!"; c= a b; print(c)}'# 输出连接结果hello, world!复制代码
数组关系操作符

for in 操作常用于遍历数组。

awk '> BEGIN { arr[1] = "a"; arr[2] = "b"; arr[3] = "c";  > for(i in arr){
> print("a[", i, "]=", arr[i])> }> }'# 遍历输出数组元素:a[ 1 ]= aa[ 2 ]= ba[ 3 ]= c复制代码
正则表达式操作符
  • 点符**.** : 匹配任意单个字符

示例:

echo -e "cat\nbat\nfun\nfin\nfan" | awk '/f.n/'funfinfan复制代码
  • **^**符:匹配开头

匹配 The 开头的字符串:

echo -e "This\nThat\nThere\nTheir\nthese" | awk '/^The/'ThereTheir复制代码
  • **$**符:匹配结尾

匹配 n 结尾的字符串:

echo -e "knife\nknow\nfun\nfin\nfan\nnine" | awk '/n$/'funfinfan复制代码
  • [] 符 :匹配字符集多选一

匹配 Call 或者 Tall:

echo -e "Call\nTall\nBall" | awk '/[CT]all/' CallTall复制代码
  • 排除匹配

使用^排除,匹配不是 Call且不是Tall的字符串:

echo -e "Call\nTall\nBall" | awk '/[^CT]all/'Ball复制代码
  • 可选匹配

匹配 Call 或者 Tall

echo -e "Call\nTall\nBall\nSmall\nShall" | awk '/Call|Ball/'CallBall复制代码
  • 符号 :0 或 1次匹配
echo -e "Colour\nColor" | awk '/Colou?r/'ColourColor复制代码
  • * 符号: 表示0或多个匹配
echo -e "ca\ncat\ncatt" | awk '/cat*/'cacatcatt复制代码
  • () 分组匹配
echo -e "Apple Juice\nApple Pie\nApple Tart\nApple Cake" | awk    '/Apple (Juice|Cake)/'   Apple JuiceApple Cake复制代码

数组

awk 'BEGIN {   fruits["mango"] = "yellow";   fruits["orange"] = "orange"   print fruits["orange"] "\n" fruits["mango"]}'orangeyellow复制代码
delete 删除数组元素
awk 'BEGIN {   fruits["mango"] = "yellow";   fruits["orange"] = "orange";   delete fruits["orange"];   for(i in fruits){print fruits[i]}}'# 删除orange后,只剩下yelloyellow复制代码
多维数组
100   200   300400   500   600700   800   900复制代码

array[0][0] 存储 100,array[0][1] 存储 200。 正确的语法是 array["0,0"] = 100

awk 'BEGIN {   array["0,0"] = 100;   array["0,1"] = 200;   array["0,2"] = 300;   array["1,0"] = 400;   array["1,1"] = 500;   array["1,2"] = 600;   # print array elements   print "array[0,0] = " array["0,0"];   print "array[0,1] = " array["0,1"];   print "array[0,2] = " array["0,2"];   print "array[1,0] = " array["1,0"];   print "array[1,1] = " array["1,1"];   print "array[1,2] = " array["1,2"];}'复制代码

字符串函数

index(str, substr)

子串 substr 出现在字符串 str 中的开始位置,从1开始计数。

awk 'BEGIN {print index("Hello", "ll")}'3复制代码
gsub(regex, sub, string)

正则匹配 regex,将其替换为 sub指定的内容, string是所选的字符串。

awk 'BEGIN { str = "Hello,World!"; gsub("World", "Lily", str); print str}'Hello,Lily!复制代码
match(str, regex)

匹配则返回regex在str中的起始位置,否则返回0表示没有匹配到。

awk 'BEGIN {str = "Hello,world!"; ret = match(str, "wo"); print str, ret}'Hello,world! 7复制代码
split(str, arr, regex)

将 str 按 regex 匹配拆分,得到的每个拆分作为元素保存在 arr 数组中。

awk 'BEGIN {str = "Hello,Hellokitty"; split(str, arr, ",");  for(ele in arr){    print arr[ele]}}'HelloHellokitty复制代码
strtonum(str)

将字符串强转成数值类型, str开头是0的话会转为八进制, 是0x或0X开头的话会转为十六进制。

awk 'BEGIN {>    print "Decimal num = " strtonum("123")>    print "Octal num = " strtonum("0123")>    print "Hexadecimal num = " strtonum("0x123")> }'Decimal num = 123Octal num = 83Hexadecimal num = 291复制代码
substr(str, start, l)

获取字串,从字符串 str 中的 start位置开始截取长度为 L 的字符串。

awk 'BEGIN {str = "nihaoya!"; print substr(str, 1, 2)}'ni复制代码
tolower(str)

将字符串 str 小写化。

awk 'BEGIN{ print tolower("HeLLo")}'hello复制代码
toupper(str)

将字符串 str 大写化。

awk 'BEGIN{ print toupper("HeLLo")}'HELLO复制代码

时间函数

systime()

获取自 1970-01-01 00:00:00 至今的unix时间戳

awk 'BEGIN {print systime()}'1545742584复制代码
mktime(datespec)

将指定的日期格式串转换为时间戳,datespec 格式是 YYYY mm dd HH MM SS

awk 'BEGIN {print mktime("2018 12 25 21 07 00")}'1545743220复制代码
strftime(format, timestamp)

将时间戳 timestamp 转换成指定格式format的字符串

awk 'BEGIN {>    print strftime("Time = %m/%d/%Y %H:%M:%S", systime())> }'Time = 12/25/2018 21:11:09复制代码

位操作函数

and

按位与

awk 'BEGIN {   num1 = 10   num2 = 6   printf "(%d AND %d) = %d\n", num1, num2, and(num1, num2)}'# 输出结果为:(10 AND 6) = 2复制代码
lshift(num, size)

将num按位左移size位数, 左移一位相当于乘以2

awk 'BEGIN {print lshift(10, 1)}'20复制代码
rshift(num, size)

将num按位右移size位数, 右移一位相当于除以2

awk 'BEGIN {print rshift(10, 1)}'5复制代码
or 按位或
awk 'BEGIN {   num1 = 10   num2 = 6   printf "(%d OR %d) = %d\n", num1, num2, or(num1, num2)}'# 输出结果为:(10 OR 6) = 14复制代码
xor 异或
awk 'BEGIN {   num1 = 10   num2 = 6   printf "(%d XOR %d) = %d\n", num1, num2, xor(num1, num2)}'# 输出结果为:(10 XOR 6) = 12复制代码

自定义函数

语法形式:

function function_name(argument1, argument2, ...) {    function body}复制代码

示例:

# Returns minimum numberfunction find_min(num1, num2){   if (num1 < num2)   return num1   return num2}# Returns maximum numberfunction find_max(num1, num2){   if (num1 > num2)   return num1   return num2}# Main functionfunction main(num1, num2){   # Find minimum number   result = find_min(10, 20)   print "Minimum =", result     # Find maximum number   result = find_max(10, 20)   print "Maximum =", result}# Script execution starts hereBEGIN {   main(10, 20)}复制代码

输出转移操作

重定向数据到文件

我们还可以将数据导入到文件中。在 print 或者 printf 后增加重定向的文件语句。 语法:

print data > outputfile

将数据 data 写入到 outputfile,如果 outputfile 不存在则创建。当指定重定向时,文件 output 会清除所有内容,然后写入数据。顺序写操作则不会提前清除文件内容,只是追加。

# 将 "Old data" 写入 message.txt 文件中,没有则创建 message.txt 文件。echo "Old data" > message.txt# 查看文件内容cat message.txt # 输出结果:Old data复制代码

然后执行:

awk 'BEGIN {print "Hello,World!" > "message.txt"}'cat message.txt # 文件的旧内容清楚了,内容已经被替换Hello,World!复制代码
追加内容到文件中

print DATA >> output-file

echo "Old data" > /tmp/message.txtcat /tmp/message.txt# 查看文件内容Old data# 追加内容到文件中awk 'BEGIN { print "Hello, World !!!" >> "/tmp/message.txt" }'cat /tmp/message.txt#  输出内容:Old dataHello, World !!!复制代码
管道 pipe

可能需要发送输出数据到其它程序,通过管道而不是文件。 这种转移方式会打开一个管道命令,并且会通过管道将数据项通过管道传到另一个进程去执行命令。 转移参数是一个 awk 表达式。

管道的语法如下:

print items | command

示例:使用 tr 命令将小写转换为大写

awk 'BEGIN { print "hello, world !!!" | "tr [a-z] [A-Z]" }'HELLO, WORLD !!!复制代码

更过关于 tr 的使用方法,可以使用 tr --help 查看帮助信息。

双向通信

awk 可以通过 |& 跟外部进程通信。

awk 'BEGIN {>    cmd = "tr [a-z] [A-Z]">    print "hello, world !!!" |& cmd>    close(cmd, "to")>    >    cmd |& getline out>    print out;>    close(cmd);> }'HELLO, WORLD !!!复制代码

说明:

  • 第一条语句,cmd="tr [a-z] [A-Z]" ,是我们建立双向通信的命令。
  • 接下来的语句,print 命令提供输入到 tr 命令。 这里的 |& 表示双向通信。
  • 第三条语句,close(cmd,"to") ,在完成执行后,关闭 to 进程。
  • cmd |& getline out 借助getline函数将结果输出 到 out 变量中。
  • 最后打印out,并使用close函数关闭命令。

整齐打印

awk 'BEGIN { printf "Hello\nWorld\n" }'# 输出结果为:HelloWorld复制代码
水平tab间隔打印
awk 'BEGIN { printf "Sr No\tName\tSub\tMarks\n" }'Sr No   Name    Sub Marks复制代码
垂直tab打印
awk 'BEGIN { printf "Sr No\vName\vSub\vMarks\n" }'# 输出结果为:Sr No     Name         Sub            Marks复制代码
回车打印
awk 'BEGIN { printf "Field 1\rField 2\rField 3\rField 4\n" }'输出:Field 4复制代码
换页打印
awk 'BEGIN { printf "Sr No\fName\fSub\fMarks\n" }'Sr No     Name         Sub            Marks复制代码
格式说明符
  • %c : 表示一个单个字符
awk 'BEGIN { printf "ASCII value 65 = character %c\n", 65 }'ASCII value 65 = character A复制代码
  • %d and %i : 表示十进制的整数
awk 'BEGIN { printf "Percentags = %d\n", 80.66 }'输出结果为:Percentags = 80复制代码
  • %e and %E : 科学记数法
awk 'BEGIN { printf "Percentags = %E\n", 80.66 }'输出结果为:Percentags = 8.066000e+01复制代码
  • %f : 浮点数
awk 'BEGIN { printf "Percentags = %f\n", 80.66 }'输出结果为:Percentags = 80.660000复制代码
  • %s : 表示字符串
awk 'BEGIN { printf "Name = %s\n", "Sherlock Holmes" }'输出结果为:Name = Sherlock Holmes复制代码
  • %nd : 指定宽度打印
awk 'BEGIN {    num1 = 10; num2 = 20; printf "Num1 = %10d\nNum2 = %10d\n", num1, num2 }'# 输出结果为:Num1 =         10Num2 =         20复制代码

AWK 概览

AWK 是一种解释性编程语言。是专门为处理文本而设计的。名字是来自于设计者的名字 —— Alfred Aho, Peter Weinberger, and Brian Kernighan.

AWK 的类型

  • AWK : AT&T 实验室
  • NAWK :AWK 的新的改进版本
  • GAWK : GNU AWK。 所有GNU/Linux发行版都是GAWK。它与AWK和NAWK完全兼容。

AWK 的典型应用场景

  • 文本处理
  • 生成格式化的文本报告
  • 处理算术操作
  • 处理字符串操作

AWK 环境

描述如何在 GNU/Linux 系统中安装 AWK 环境。

安装包管理器

一般情况下, AWK 默认在大都数 GNU/Linux 系统中都是安装发行的。 你可以使用 which 命令,检查awk在系统中是否安装好了。 如果没有安装 awk, 可以按如下命令借助 高级安装包 APT安装 AWK:

sudo apt-get updatesudo apt-get install gawk复制代码
yum install gawk# 查看which awk# 输出结果为:/bin/awk复制代码

从源代码中安装:

  • wget
  • tar xvf gawk-4.1.1.tar.xz
  • ./configure
  • make
  • make check
  • sudo make install
  • which awk

转载于:https://juejin.im/post/5c4570cb6fb9a04a006f52db

你可能感兴趣的文章
架构阅读笔记5
查看>>
IIS5.1使用虚拟目录部署网站
查看>>
Git 深度学习填坑之旅三(分支branch、远程操作)
查看>>
括号匹配问题
查看>>
UVA 10766 Organising the Organisation
查看>>
「美团 CodeM 复赛」城市网络
查看>>
python 将Excel表格中的一列数据转化成多行数据
查看>>
Go多线程与channel通信
查看>>
找水王
查看>>
多个线程之间共享数据的方式(卖票问题,存取款问题)
查看>>
观察者模式
查看>>
Bzoj2882 工艺 [线性算法]
查看>>
Bzoj2251 [2010Beijing Wc]外星联络
查看>>
python 发送邮件
查看>>
在凡客四个月的工作总结
查看>>
Qt颜色下拉框
查看>>
31、springboot与任务
查看>>
【转】 一个fork的面试题
查看>>
20131108
查看>>
django.http.request中HttpRequest对象的一些属性与方法
查看>>