(1)awk介绍

awk是由Alfred Aho Peter Weinberger Brian Kernighan1977年开发的变成语言,awk是上述三位创建者姓的首字母。

Awk的基本语法与c语言类似,如果对c语言很熟悉,那么学习awk编程也将事半功倍。

Awk功能与sed相似,都是用来进行文本处理的,awk语言可以从文件或字符串中基于指定规则浏览和抽取信息,在抽取信息的基础上,才能进行其他文本操作。

 

awk是一款设计用于数据流的工具。它颇有玩头的原因就在于可以对列和行进行操作。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处。灵活性是awk最大的优势。

 

 

(2)awk工作原理

awk程序由一个主输入循环维持,主输入循环反复执行,直到终止条件被触发。

主输入循环无须人工书写,awk已经搭好主输入循环的框架。

主输入循环自动依次读取输入文件行,以供处理,处理文件的动作根绝不同功能需求来进行添加。

Awk编程模型三个阶段:

  • 读输入文件之前的执行代码段-BEGIN关键字标识

  • 读取输入文件时的执行代码

  • 读输入文件完毕之后的执行代码段-END关键字标识

 

awk脚本的结构基本如下所示:

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

awk命令也可以从stdin中读取。

awk脚本通常由3部分组成。BEGINEND和带模式匹配选项的常见语句块。这3个部分都是可选项,在脚本中可省略任意部分。

 

 

awk命令的工作方式如下所注。

(1) 执行BEGIN { commands } 语句块中的语句。

(2) 从文件或stdin中读取一行,然后执行pattern { commands }。重复这个过程,直到文件全部被读取完毕。

(3) 当读至输入流末尾时,执行END { commands } 语句块。


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


END语句块和BEGIN语句块类似。END语句块在awk从输入流中读取完所有的行之后即被执行。像打印所有行的分析结果这类汇总信息,都是在END语句块中实现的常见任务(例如,在比较过所有的行之后,打印出最大数)。它也是一个可选的语句块。


最重要的部分就是pattern语句块中的通用命令。这个语句块同样是可选的。如果不提供该语句块,则默认执行{ print },即打印所读取到的每一行。awk对于每一行,都会执行这个语句块。这就像一个用来读取行的while循环,在循环体中提供了相应的语句。


每读取一行,awk就会检查该行和提供的样式是否匹配。样式本身可以是正则表达式、条件语句以及行匹配范围等。如果当前行匹配该样式,则执行{ }中的语句。


样式是可选的。如果没有提供样式,那么awk就认为所有的行都是匹配的,并执行{ }中的语句。



(3)BEGINEND

Awk中定义了两个特殊的字段:BEGINEND

BEGIN用于在主输入循环之前执行,即在未读取输入文件行之前执行。

END则相反,用于在主输入循环之后执行,即在读取输入文件行完毕后执行。

 

计算文本行数

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk 'BEGIN{x=0}{x++}END{print x}'
3
[root@Test01 awk]#

 

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk 'END{print NR}'
3
[root@Test01 awk]#

这里只使用了END语句块。每读入一行,awk会将NR更新为对应的行号。当到达最后一行时,NR中的值就是最后一行的行号,于是,位于END语句块中的NR就包含了文件的行数。

 

我们通常将变量初始化语句(如var=0)以及打印文件头部的语句放入BEGIN语句块中。在END{}语句块中,往往会放入打印结果等语句。

 

 

 

(4)awk执行三种方式

调用awk的方法与调用sed类似,也有三种方式,一种为shell命令行方式,另两种是将awk程序写入脚本文件,然后执行该脚本文件

  • shell命令行输入命令调用awk

格式:awk [-F 域分隔符] ‘awk 程序段’ 输入文件
  • awk程序段插入脚本文件,然后通过awk命令调用

sed命令类似,awk也用-f选项表示调用awk脚本文件

格式为:awk -f awk脚本文件输入文件
  • sed命令插入脚本文件后,设置脚本为可执行

设置可执行后,直接运行该脚本文件。

这种方式调用awkawk脚本要以#!/bin/awk –f开头

格式:#./awk脚本文件输入文件


(5)、模式匹配

任何awk语句都由模式-pattern和动作-action组成。

模式是一组用户测试输入行是否需要执行动作的规则,动作是包含语句、函数和表达式的执行过程。

简言之,模式决定动作何时触发,动作执行对输入行的处理。

Awk模式匹配经常需要用到正则表达式,awk除支持基本正则表达式,还支持”?””+”两个扩展元字符,grepsed并不支持。

示例1

 
[root@Test01 awk]# cat server.txt
10.64.8.1 root 123
 
10.64.8.2 root 456
 
10.64.8.90 root 8888
[root@Test01 awk]# cat server.txt |awk '/90/'
10.64.8.90 root 8888
[root@Test01 awk]#
[root@Test01 awk]# cat server.txt |awk '/90/{print "this is 90server" }'
this is 90server
[root@Test01 awk]# cat server.txt |awk '/^$/{print "this is a blank line" }'
this is a blank line
this is a blank line
[root@Test01 awk]#

示例采用的是第一种调用方式,单引号中间是awk命令。

awk命令由两部分组成,以/符号分隔,^$部分是模式,花括号部分是动作,该命令表示一旦读入的输入文件行是空行,就打印”this is blank line”

^$是正则表达式,表示空行,print表示该动作是打印操作。

 

示例2

$ awk 'NR < 5' # 行号小于5的行
$ awk 'NR==1,NR==4' # 行号在1到5之间的行
$ awk '/linux/' # 包含样式linux的行(可以用正则表达式来指定模式)
$ awk '!/linux/' # 不包含包含模式为linux的行

 


(6)、记录和域

Awk认为输入文件是结构化的,awk将每个输入文件行定义为记录,行中的每个字符串定义为域,域之间用空格、tab键或其他符号进行分隔,分隔域的符号叫做分隔符。

两个或多个连续的空格或tab键当做一个分隔符来处理。

$awk中叫做域操作符,域操作符后面跟数字或变量来标识域的位置。

$0打印全部域


$后面跟数字

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.2 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{print $1}'
10.64.8.1
10.64.8.2
10.64.8.90
[root@Test01 awk]# cat server1.txt |awk '{print $0}'
10.64.8.1 root 123
10.64.8.2 root 456
10.64.8.90 root 8888
[root@Test01 awk]#

 

$后面跟表达式

[root@Test01 awk]# cat server1.txt |awk 'BEGIN {one=1;two=2}{print $one}'
10.64.8.1
10.64.8.2
10.64.8.90
[root@Test01 awk]# cat server1.txt |awk 'BEGIN {one=1;two=2}{print $one,$two}'
10.64.8.1 root
10.64.8.2 root
10.64.8.90 root
 

$后面跟字符串

[root@Test01 awk]# cat server1.txt |awk 'BEGIN {one=1;two=2}{print $one,$two,"papapa"}'
10.64.8.1 root papapa
10.64.8.2 root papapa
10.64.8.90 root papapa
[root@Test01 awk]# cat server1.txt |awk 'BEGIN {one=1;two=2}{print $one,$two,"papapa",$(one+two)}'
10.64.8.1 root papapa 123
10.64.8.2 root papapa 456
10.64.8.90 root papapa 8888
[root@Test01 awk]#

 

 

$后面跟全局变量

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.2 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{print $NF}'
123
456
8888
[root@Test01 awk]#

 

 

(7)-F选项

Awk的默认域分隔符是空格。Tab键被看做是连续的空格键来处理。

使用-F选项来改变分隔符。

[root@Test01 awk]# cat server2.txt
10.64.8.1,root,123
10.64.8.2,root,456
10.64.8.90,root,8888
[root@Test01 awk]# cat server2.txt |awk -F',' '{print $1}'
10.64.8.1
10.64.8.2
10.64.8.90
[root@Test01 awk]# cat server2.txt |awk -F',' '{print $1,$3}'
10.64.8.1 123
10.64.8.2 456
10.64.8.90 8888
[root@Test01 awk]#
 

 

环境变量FS

FS变量也可以做域分隔,通过在BEGIN字段中设置FS的值来改变分隔符。

[root@Test01 awk]# cat server2.txt
10.64.8.1,root,123
10.64.8.2,root,456
10.64.8.90,root,8888
[root@Test01 awk]# cat server2.txt |awk  'BEGIN {FS=","} {print $1,$3}'
10.64.8.1 123
10.64.8.2 456
10.64.8.90 8888
[root@Test01 awk]#

 

(8)、关系和布尔运算符

关系运算符

Awk定义了一组关系运算符用于awk模式匹配

  • < 小于

  • > 大于

  • <= 小于等于

  • >= 大于等于

  • == 等于

  • != 不等于

  • ~ 匹配正则表达式

  • !~ 不匹配正则表达式

 

 

[root@Test01 awk]# cat /etc/passwd|awk -F':' '$1~/root/{print }'
root:x:0:0:root:/root:/bin/bash
 
[root@Test01 awk]# cat /etc/passwd|awk -F':' '$1=="root"{print }'
root:x:0:0:root:/root:/bin/bash
 
[root@Test01 awk]# cat /etc/passwd|awk -F':' '{if($1=="root")print }'
root:x:0:0:root:/root:/bin/bash
[root@Test01 awk]#
 

 

布尔运算符

为了进行多条件模式匹配,awk定义了三个布尔运算符表示多条件之间的关系

  • || 逻辑或

  • && 逻辑与

  • ! 逻辑非

 

[root@Test01 awk]# cat /etc/passwd|awk -F':' '{if($1=="root"||$1=="xiaoqq")print }'
root:x:0:0:root:/root:/bin/bash
xiaoqq:x:502:502::/home/xiaoqq:/bin/bash
[root@Test01 awk]#

 


(9)、表达式

与其他编程语言一样,awk表达式用于存储、操作和获取数据,一个awk表达式可以数值、字符常量、变量、操作符、函数和正则表达式自由组合而成。

awk算数运算符

  • +

  • -

  • *

  • /

  • %

  • ^** 乘方

  • ++x 在返回x值之前,x变量加1

  • x++ 在返回x值之后,x变量加1

 

计算文本中空行的行数

[root@Test01 awk]# cat a1.txt
123
 
456
 
566
[root@Test01 awk]# cat a1.txt |awk '/^$/{x=x+1}END{print x}'
2
[root@Test01 awk]#
[root@Test01 awk]# cat a1.txt |grep  "^$"|wc -l
2

 

 

计算学生平均分

[root@Test01 awk]# cat a2.txt
tom 12 13 14
luci 20 2 19
xiaoming 18 60 7
[root@Test01 awk]# cat a2.txt |awk '{total=$2+$3+$4;agv=total/3;print $1,agv}'
tom 13
luci 13.6667
xiaoming 28.3333
[root@Test01 awk]#

 

(10)、系统变量

awk定义来了很多内建变量用于设置环境信息,我们称他们为系统变量,这些变量可以分为两种

  • 第一种用于改变awk的默认值,如域分隔符

  • 第二种用于定义系统值,在处理文本时可以读取这些系统值,如记录中的域数量,当前记录数、当前文件名等,awk动态改变第2种系统变量的值。



awk环境变量极其意义

  • $n 当前记录的第n个域,域间由FS分割

  • $0 记录的所有域

  • ARGC 命令行参数的数量

  • ARGIND 命令行中当前文件的位置-0开始标号

  • ARGV 命令行参数的数组

  • CONVFMT 数字转换格式

  • ENVIRON 环境变量关联数组

  • ERRNO 最后一个系统错误的描述

  • FIELDWIDTHS 字段宽度列表,以空格键分隔

  • FILENAME 当前文件名

  • FNR 浏览文件的记录数

  • FS 字段分隔符,默认是空格

  • IGNORECASE 布尔变量,如果为真,则进行忽略大小写的匹配

  • NF 当前记录中的域数量

  • NR 当前记录数

  • OFMT 数字的输出格式

  • OFS 输出域分隔符,默认是空格

  • ORS 输出记录分隔符,默认是换行符

  • RLENGTH match函数所匹配的字符串长度

  • RS 记录分隔符,默认是空格键

  • RSTART match函数所匹配的字符串的第一个位置

  • SUBSEP 数组下标分隔符、默认值是\034

 

(11)、格式化输出

print

print只提供了简单的输出功能。

当使用不带参数的print时,它会打印出当前行。关于print,需要记住两件重要的事情:

  • print的参数是以逗号进行分隔时,参数打印时则以空格作为定界符。

  • awkprint语句中,双引号是被当做拼接操作符(concatenation operator)使用的。


[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{print $1""$2}'
10.64.8.1root
10.64.8.4root
10.64.8.90root
[root@Test01 awk]# cat server1.txt |awk '{print $1":"$2":"$3}'
10.64.8.1:root:123
10.64.8.4:root:456
10.64.8.90:root:8888
[root@Test01 awk]#





printf

printf语句可以定义输出的格式,语法如下:

printf (格式控制符,参数)


printf语句包含两部分

  • 第一部分,格式控制符,都以%符号开始,用于描述格式规范

  • 第二部分,参数列表,比如变量名列表,与格式控制符相对应,是输出的对象。


格式控制符分为:

  • awk修饰符

-      左对齐

width 域的步长

.prec 小数点右边的位数


  • awk格式符

%c ASCII字符

%d 整型数

%e 浮点数,科学计数法

%f 浮点数

%o 八进制数

%s 字符串

%x 十六进制数


[root@Test01 awk]# cat server2.txt
10.64.8.1,root,123
10.64.8.2,root,456
10.64.8.90,root,8888
[root@Test01 awk]# cat server2.txt |awk 'BEGIN{FS=","}{printf("\t%s\t\t%s\t\t%s\n",$1,$2,$3)}'
        10.64.8.1               root            123
        10.64.8.2               root            456
        10.64.8.90              root            8888
[root@Test01 awk]#



(12)、内置函数

awk提供了强大的内置字符串函数,用于实现文本的字符串替换、查找以及分隔等功能

awk字符串函数列表

  • gsub(r,s)

在输入文件中用s替换r

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.2 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk 'gsub("10.64.8.1","10.64.8.8")'
10.64.8.8 root 123
[root@Test01 awk]#


  • gsub(r,s,t)

t中用s替换r

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.2 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk 'gsub(/8.1/,"8.8",$1)'
10.64.8.8 root 123
[root@Test01 awk]#
  • index(s,t)

返回s中字符串第一个t的位置

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{n=index($1,"4");print n}'
5
5
5
[root@Test01 awk]# cat server1.txt |awk '{n=index($2,"4");print n}'
0
0
0
[root@Test01 awk]# cat server1.txt |awk '{n=index($3,"4");print n}'
0
1
0
[root@Test01 awk]#
  • length(s)

返回s的长度

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{n=length($3);print n}'
3
3
4
[root@Test01 awk]#
  • match(s,t)

测试s是否包含匹配t的字符串

t可以是一个正则表达式,若匹配成功,返回匹配t的首位置,若不成功,则返回0

[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{n=match($3,/8/);print n}'
0
0
1
  • split(r,s,t)

用分隔符t,将r分成序列s

t不指定的话,使用模式分隔符FS

[root@Test01 awk]# echo "12:33:00"|awk '{split($1,a,":");print a[1],a[2],a[3]}'
12 33 00
  • sub(r,s,t)

t中第1次出现的r替换为s

[root@Test01 awk]# echo "aaa"|awk '{sub("a","b",$1);print}'
baa
  • substr(r,s)

返回字符串r中从s开始的后缀部分

[root@Test01 awk]# echo -e "aaaaabcc8989\n7777b9999"|awk '{n=substr($1,8);print n}'
c8989
99
  • substr(r,s,t)

返回字符串r中从s开始长度为t的后缀部分

[root@Test01 awk]# echo -e "aaaaabcc8989\n7777b9999"|awk '{n=substr($1,8,2);print n}'
c8
99



 

(13)、条件语句

awk条件语句和c语言的语法完全一样。

条件语句if的语法如下

if (条件表达式)
动作1
else
    动作2



[root@Test01 awk]# cat server1.txt
10.64.8.1 root 123
10.64.8.4 root 456
10.64.8.90 root 8888
[root@Test01 awk]# cat server1.txt |awk '{if($1=="10.64.8.1")print $1; else print "a"}'
10.64.8.1
a
a
 
#格式化awk语句
[root@Test01 awk]# cat server1.txt |awk '{
     if($1=="10.64.8.1"){
         print $1
     }
     else {
         print "a"
     }
}
'
10.64.8.1
a
a
[root@Test01 awk]#
[root@Test01 awk]# cat server1.txt |awk '{if($1=="10.64.8.1")print $1}'
10.64.8.1
[root@Test01 awk]#

 

(14)、循环

循环语句有三种:whiledo whilefor


While循环语法如下:

While (条件表达式)
    动作

 

do while语法如下

do
动作
    While (条件表达式)

 

 

for循环语法如下:

 
for (设置计数器初值;测试计数器;计数器变化)
    动作

例如

for(i=0;i<10;i++) { print $i ; }

或者

for(i in array) { print array[i]; }

 

 

 

 

 

(15)、数组

数组是用于存储一些列值的变量,这些值之间通常是有联系的,可通过索引来访问数组的值,索引需要用中括号括起,数组的基本格式为:

array[index]=value

awk数组无须定义数组类型和大小,而可以直接赋值后使用。

 1)、关联数组

关联数组是指数组的索引可以是字符串,也可以是数字。

在大部分编程语言中,数组的索引只能是数字,数组表示了存储值的一系列地址,数组索引是存储地址的顺序来决定的,如c语言中array[0]表示数组的起始地址。

而关联数组在索引和数组元素值之间建立器关联,对每一个数组元素,awk自动维护了一对值:索引和数组元素值。


关联数组的值无须以连续的地址进行存储,因此,关联数组即便可以使用数字作为索引,但是该数字索引并表示数组存储地址的信息。


Awk的所有数组都是关联数组,这是awk数组和其他大部分编程语言数组的本质区别。


关联数组访问

Awk特别定义了一种for循环用来访问关联数组,语法如下

for (variable in array)
    do something with array[variable]


array是已定义的数组名,variable是任意指定的变量,可以看做是for循环中定义的临时变量。


关键字in也可用在条件表达式中判断元素是否在数组中,条件表达式格式为:

index in array

如果array[index]存在,则返回1,否则返回0.


 
awk 'BEGIN{
  a["index1"]=11;
  a["index2"]=22;
  for(i in a){
    print i,a[i]
  }
}'


[root@Test01 awk]# awk 'BEGIN{
>   a["index1"]=11;
>   a["index2"]=22;
>   for(i in a){
>     print i,a[i]
>   }
> }'
index1 11
index2 22
[root@Test01 awk]#






  • 2)、split函数

用分隔符t,将r分成序列s

t不指定的话,使用模式分隔符FS

 

 

 

echo "12 23 44"|awk '{
    split($0,a," ")
    print a[1],a[2],a[3]
    for(i in a){
        print a[i]
    }
}
'

 

[root@Test01 awk]#
[root@Test01 awk]# echo "12 23 44"|awk '{
>     split($0,a," ")
>     print a[1],a[2],a[3]
>     for(i in a){
>         print a[i]
>     }
> }
> '
12 23 44
12
23
44

 

 

 

  • 3)、数组形式的系统变量


ARGV-

echo "12:23:00"|awk -F':'  '{
  for (i in ARGV){
    print ARGV[i]
  }
  print ARGC
 
}
'


[root@Test01 awk]# echo "12:23:00"|awk -F':'  '{
>   for (i in ARGV){
>     print ARGV[i]
>   }
>   print ARGC
>
> }
> '
awk
1
[root@Test01 awk]#


ENVIRON


awk '
  BEGIN {
    for (i in ENVIRON) {
 print i "=" ENVIRON[i]
    }
  }
'


 

[root@Test01 awk]# awk '
>   BEGIN {
>     for (i in ENVIRON) {
> print i "=" ENVIRON[i]
>     }
>   }
> '
TERM=vt100
G_BROKEN_FILENAMES=1
SHLVL=1
PWD=/root/shell/test/awk
HISTTIMEFORMAT=%F %T
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/mysql-5.7.17/bin/:/root/bin
OLDPWD=/root/shell/test
AWKPATH=.:/usr/share/awk
_=/bin/awk
LANG=zh_CN.UTF-8
LS_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:
SSH_CONNECTION=10.8.41.231 53019 172.23.54.84 22
MAIL=/var/spool/mail/root
HOSTNAME=Test01
HISTFILE=/usr/share/.history/root/10.8.41.231.history.20170907_193512
USER=root
HISTFILESIZE=40000
HISTSIZE=4000
SSH_TTY=/dev/pts/1
SHELL=/bin/bash
LESSOPEN=||/usr/bin/lesspipe.sh %s
LOGNAME=root
HOME=/root
HISTCONTROL=ignoredups
SSH_CLIENT=10.8.41.231 53019 22
[root@Test01 awk]#
 
 

 

 

(16)、将外部变量值传递给awk

借助选项 -v,我们可以将外部值(并非来自stdin)传递给awk

$ VAR=10000
$ echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
10000


还有另一种灵活的方法可以将多个外部变量传递给awk,例如:

$ var1="Variable1" ; var2="Variable2"
$ echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
Variable1 Variable2


当输入来自于文件而非标准输入时,使用下列命令:

$ awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename

在上面的方法中,变量之间用空格分隔,以键-值对的形式(v1=$var1 v2=$var2)作为awk的命名行参数紧随在BEGIN{}END语句块之后。



(17)、用getline读取行

awk通常默认读取一个文件的所有行。如果只想读取某一行,可以使用getline函数。有时候,我们需要从BEGIN语句块中读取第一行。

语法:

getline var。

变量var就包含了特定行的内容。如果调用不带参数的getline,我们可以用 $0$1$2访问文本行的内容。

[root@Test01 awk]# seq 5
1
2
3
4
5
[root@Test01 awk]# seq 5|awk 'BEGIN{getline}{print "a",$0}'
a 2
a 3
a 4
a 5
[root@Test01 awk]# seq 5|awk 'BEGIN{getline;print}{print "a",$0}'
1
a 2
a 3
a 4
a 5
[root@Test01 awk]# seq 5|awk 'BEGIN{getline;print $0}{print "a",$0}'
1
a 2
a 3
a 4
a 5
[root@Test01 awk]# seq 5|awk 'BEGIN{getline var;print var }{print "a",$0}'
1
a 2
a 3
a 4
a 5
[root@Test01 awk]#
 
 

 


(18)awk中运行shell命令

将命令的输出结果读入变量output的语法如下:

"command" | getline output ;

在下面的代码中,echo会生成一个空白行。变量cmdout包含命令grep root /etc/passwd的输出,该命令会打印出包含root的行。

[root@Test01 awk]# echo | awk '{"echo 123"|getline var;print var }'
123
[root@Test01 awk]# echo | awk '{"grep root /etc/passwd"|getline var;print var }'
root:x:0:0:root:/root:/bin/bash
[root@Test01 awk]#

通过使用getline,我们将外部shell命令的输出读入变量cmdout