11 shell文本处理利器awk命令


11.1  awk入门
awk是一种非常强大的数据处理工具,其本身可以称为是一种程序设计语言,因而具有其他程序设计语言所共同拥有的一些特征,例如变量、函数以及表达式等。通过awk,用户可以编写一些非常实用的文本处理工具。本节将介绍awk的基础知识。

11.1.1  awk的功能
awk是Linux以及UNIX环境中现有的功能最强大的数据处理工具。简单地讲,awk是一种处理文本数据的编程语言。awk的设计使得它非常适合于处理由行和列组成的文本数据。而在Linux或者UNIX环境中,这种类型的数据是非常普遍的。
除此之外,awk还是一种编程语言环境,它提供了正则表达式的匹配,流程控制,运算符,表达式,变量以及函数等一系列的程序设计语言所具备的特性。它从C语言等中获取了一些优秀的思想。awk程序可以读取文本文件,对数据进行排序,对其中的数值执行计算已经生成报表等。

11.1.2  awk命令的基本语法
awk命令的基本语法如下:
awk pattern { actions  }
在上面的语法中,pattern表示匹配模式,actions表示要执行的操作。以上语法表示,当某个文本行符合pattern指定的匹配规则时,执行actions所执行的操作。在上面的语法中,pattern和actions都是可选的,但是两者必须保证至少有一个。如果省略匹配模式pattern,则表示对所有的文本行执行actions所表示的操作;如果省略actions,则表示将匹配成功的行输出到屏幕。

11.1.3  awk的工作流程
对于初学者来说,搞清楚awk的工作流程非常重要。只有在掌握了awk的工作流程之后,才有可能用好awk来处理数据。在awk处理数据时,它会反复执行以下4个步骤:
(1)自动从指定的数据文件中读取行文本。
(2)自动更新awk的内置系统变量的值,例如列数变量NF、行数变量NR、行变量$0以及各个列变量$1、$2等等。
(3)依次执行程序中所有的匹配模式及其操作。
(4)当执行完程序中所有的匹配模式及其操作之后,如果数据文件中仍然还有为读取的数据行,则返回到第(1)步,重复执行(1)~(4)的操作。

11.1.4  执行awk程序的几种方式
1.通过命令行执行awk程序,语法如下:
awk 'program-text' datafile

#输出所有的行
{ print  }

2.执行awk脚本
在awk程序语句比较多的情况下,用户可以将所有的语句写在一个脚本文件中,然后通过awk命令来解释并执行其中的语句。awk调用脚本的语法如下:
awk -f program-file file ..
在上面的语法中,-f选项表示从脚本文件中读取awk程序语句,program-file表示awk脚本文件名称,file表示要处理的数据文件。

3.可执行脚本文件
在上面介绍的两种方式中,用户都需要输入awk命令才能执行程序。除此之外,用户还可以通过类似于Shell脚本的方式来执行awk程序。在这种方式中,需要在awk程序中指定命令解释器,并且赋予脚本文件的可执行权限。其中指定命令解释器的语法如下:
#!/bin/awk -f
以上语句必须位于脚本文件的第一行。然后用户就可以通过以下命令执行awk程序:
awk-script file
其中,awk-script为awk脚本文件名称,file为要处理的文本数据文件。

#! /bin/awk -f
#输出所有的行
{ print  }

11.2  awk的模式匹配
在awk中,匹配模式处于非常重要的地位,它决定着匹配模式后面的操作会影响到哪些文本行。awk中的匹配模式主要包括关系表达式、正则表达式、混合模式,BEGIN模式以及END模式等,本节将对这些模式匹配进行详细地介绍。

11.2.1  关系表达式
awk提供了许多关系运算符,例如大于>、小于<或者等于==等,关于关系运算符的详细使用方法,将在第4节中详细介绍。awk允许用户使用关系表达式作为匹配模式,当某个文本行满足关系表达式时,将会执行相应的操作。

#! /bin/bash
#打印第2列的成绩超过80的行
result=`awk '$2 > 80 { print  }' scores.txt`
echo "$result"

11.2.2  正则表达式
awk支持以正则表达式作为匹配模式,与sed一样,用户需要将正则表达式放在两条斜线之间,其基本语法如下:
/regular_expression/

#! /bin/bash
#输出以字符T开头的行
result=`awk '/^T/ { print  }' scores.txt`
echo "$result"

#! /bin/bash
#输出以Tom或者Kon开头的行
result=`awk '/^(Tom|Kon)/ { print  }' scores.txt`
echo "$result"

11.2.3  混合模式
awk不仅支持单个的关系表达式或者正则表达式作为模式,还支持使用逻辑运算符&&、||或者!将多个表达式组合起来作为一个模式。其中,&&表示逻辑与,||表示逻辑或,!表示逻辑非,关于这3个运算符的详细用法,将在第4节中介绍。

#! /bin/bash
#混合模式
result=`awk '/^K/ && $2 > 80 { print  }' scores.txt`
echo "$result"

11.2.4  区间模式
awk还支持一种区间模式,也就是说通过模式可以匹配一段连续的文本行。区间模式的语法如下:
pattern1, pattern2
其中,pattern1和pattern2都是前面所讲的匹配模式,可以是关系表达式,也可以是正则表达式等。当然,也可以是这些模式的混合形式。

#! /bin/bash
#区间模式
result=`awk '/^Nancy/, $2==92 { print }' scores.txt`
echo "$result"

11.2.5  BEGIN模式
BEGIN模式是一种特殊的内置模式,其成立的时机为awk程序刚开始执行,但是又尚未读取任何数据之前。
因此,该模式所对应的操作仅仅被执行一次,当awk读取数据之后,BEGIN模式便不再成立。所以,用户可以将与数据文件无关,而且在整个程序的生命周期中,只需执行1次的代码放在BEGIN模式对应的操作中。

#! /bin/awk -f
#通过BEGIN模式输出字符串
BEGIN { print "Hello! World." }

#! /bin/awk -f
#通过BEGIN模式初始化变量
BEGIN {
    FS="[\t:]"
    RS="\n"
    count=30
    print "The report is about students's scores."
}

11.2.6  END模式
END模式是awk的另外一种特殊模式,该模式成立的时机与BEGIN模式恰好相反,它是在awk命令处理完所有的数据,即将退出程序时成立,在此之前,END模式并不成立。
无论数据文件中包含多少行数据,在整个程序的生命周期中,该模式所对应的操作只被执行1次。因此,一般情况下,用户可以将许多善后工作放在END模式对应的操作中。

#! /bin/awk -f
#输出报表头
BEGIN {
    print "scores report"
    print "================================="
}
#输出数据
{ print  }
#报表完成
END {
    print "================================"
    print "printing is over"
}

11.3  变量
与其他的程序设计语言一样,awk本身支持变量的相关操作,包括变量的定义和引用,以及参与相关的运算等。此外,还包含了许多内置的系统变量。本节将介绍awk中的变量的相关知识。

11.3.1  变量的定义和引用
变量的作用是用来存储数据。变量由变量名和值两部分组成,其中变量名是用来实现变量值的引用的途径,而变量值则是内存空间中存储的用户数据。
awk的变量名只能包括字母、数字和下划线,并且不能以数字开头。例如abc、a_、_z以及a123都是合法的变量名,而123abc则是非法的变量名。另外,awk的变量名是区分大小写的,因此,X和x分别表示不同的变量。
在awk中定义变量的方法非常简单,只要给出一个变量名并且赋予适当的值即可。
awk中的变量类型分为两种,分别为字符串和数值。但是在定义awk变量时,毋需指定变量类型,awk会根据变量所处的环境自动判断。如果没有指定值,数值类型的变量的缺省值为0,字符串类型的变量的缺省值为空串。

#! /bin/awk -f

BEGIN {
    #定义变量x
    x=3
    #定义变量message
    message="Hello " "world"
    #输出变量
    print x
    print message
}

11.3.2  系统内置变量
akw提供了许多非常实用的系统变量,例如字段变量、字段数变量以及记录数变量等。
变量    说明
$0      记录变量,表示当前记录
$n      字段变量,其中n为整数,且n>1,表示第n个字符的值
NF      整数值,表示当前记录的字段数
NR      整数值,表示awk已经读入的字段数
FILENAM 表示正在处理的数据文件的名称
RS      记录分隔(record seperator)字符,默认值是换行符
FS      字段分割(field seperator)字符,默认值是空格或者制表符

11.3.3  记录分隔符RS和字段分隔符FS
记录分隔符使用系统变量RS来指定,如果没有指定,则默认为换行符\n。在绝大部分的情况下,这种方式都是有效的,因为awk每次都是从数据文件中只读取一行数据进行处理。
所以正常情况下,一行数据就代表一条记录。但是,这并不意味着总是这样,有些数据文件中用多行文本来描述一条记录

#! /bin/awk -f
{
    #输出每行数据
    print
    print "=========================================="
}

#! /bin/awk -f
BEGIN {
    #定义记录分隔符
    RS=""             
}
   
{
    print
    print "=========================================="           
}


#! /bin/awk -f
BEGIN {
    #定义记录分隔符
    RS=""
    #定义字段分隔符
    FS="\n"
}
#输出第1个字段
{ print $1 }

11.3.4  记录和字段的引用
在awk中,用户可以使用系统变量来引用数据文件中的记录和字段。
与关系型数据库不同,awk每次只是读取1行文本,因此,在awk程序中,所说的记录和字段的引用都是针对当前记录来说的。
变量$0表示正在读取的当前的记录,该变量将整个记录作为一个字符串来处理。

#! /bin/awk -f
#通过$0引用整个记录
{ print $0  }

#! /bin/awk -f
{
    #输出第1个字段以及第2~5个字段的和
    print $1, $2+$3+$4+$5
}

11.4  运算符和表达式
awk是一种编程语言环境,因此,它也支持常用的运算符以及表达式,例如算术运算、逻辑运算以及关系运算等。本节将对awk所支持的常用的运算符以及表达式进行介绍。

11.4.1  算术运算符
awk支持常用的算术运算,这一点与其他的程序设计语言基本相同
运算符  说明
+       加法运算
-       减法运算
*       乘法运算
/       除法运算
%       求模运算
^       指数运算

#! /bin/awk -f
BEGIN {
    #除法运算
    x=5/2
    print x
    #求模运算
    x=5%2
    print x
    #指数运算
    x=2^3
    print x
}

11.4.2  赋值运算符
= += -= *= /= %= ^=

#! /bin/awk -f
BEGIN {
    #简单赋值
    x=4
    print x
    #求和赋值
    x+=10
    print x
    #乘积赋值
    x*=2
    print x
    #幂运算赋值
    x^=2
    print x
}

11.4.3  条件运算符
awk中的条件运算符只有一个,其语法如下:
expression ? value1 : value2
这是一个三目运算符,当表达式expression的值为真时,返回值为value1;否则,返回值为value2。

#! /bin/awk -f
{
    #如果大于90,输出A,否则输出B
    grade=($2>90?"A":"B")
    print grade
}

11.4.4  逻辑运算符
awk支持3种逻辑运算,分别为逻辑与(&&)、逻辑或(||)和逻辑非(!);

#! /bin/awk -f
#输出所有的字段的值都大于80的记录
$2 > 80 && $3 > 80 && $4 > 80 && $5 >80 {
    print
}

11.4.5  关系运算符
awk支持常用的关系运算符,例如大于、小于以及等于;

#! /bin/awk -f
#匹配第1个字段以字符K开头的记录
$1 ~ /^K/ { print  }

11.4.6  其他运算符
除了前面介绍的运算符之外,awk还支持其他的一些运算符,例如正号+、负号-、自增++以及自减--等。这些运算符的使用方法与其他的语言的使用方法完全相同,不再举例说明。

11.5  函数
awk提供函数的支持。awk本身提供了许多系统函数,例如字符串函数以及算术函数。另外,用户还可以自定义函数。由于自定义函数使用非常少,所以本节主要介绍awk提供的系统函数。

11.5.1  字符串函数
字符串是awk中的两大类型之一,awk提供了一些常见的字符串处理函数,例如index()、length()以及match()等,下表列出了常用的字符串函数。

index(string1, string2)
    返回string2在string1中的位置;如果string1不包含string2则返回0;

length(string)
    返回字符串string的长度;

match(string, regexp)
    在字符串string中搜索符合正则表达式regexp的(第一个)子字符串,返回值体现在系统变量RSTART和RLENGTH中;

split(string, array, seperator)
    根据指定的分隔符seperator,将字符串string分割成多个字段,并存储到array数组中;

sub(regexp, replacement, string)
    将字符串string中的第1个符合正则表达式regexp的子字符串全部替换为replacement;

gsub(regexp, replacement, string)
    将字符串string中的所有符合正则表达式regexp的子字符串全部替换为replacement;

substr(string, start, [length])
    从字符串string中截取指定的字符串,起始位置为start,长度为length;如果省略length,则表示从start开始一直截取到字符串结束;

1.index(string1, string2)
该函数用来定位字符串string2在字符串string1中出现的位置。如果出现多次,则返回第1次出现的位置;如果string1不包含string2,则该函数返回0。该函数区分大小写,用户在使用时一定要注意。
#! /bin/awk -f
BEGIN {
    #输出子串在父串中出现的位置
    print index("Hello,world.","world")
}

2.length(string)
该函数的返回值为整数,表示字符串string的长度。
#! /bin/awk -f
BEGIN {
    #输出字符串的长度
    print length("Hello, world.")
}

3.match(string, regexp)
该函数的第1个参数为字符串,第2个参数为正则表达式,其功能是在字符串string中搜索匹配正则表达式的子串。
用户可以通过系统变量RSTART和RLENGTH来获取相关的返回值。
其中,
RSTART用来返回正则表达式匹配的子串在父串中出现的位置,如果匹配不成功,则返回0。
RLENGTH用来返回正则表达式匹配的子串的长度,如果匹配不成功,则返回-1。

#! /bin/awk -f
BEGIN {
    #通过正则表达式搜索子串
    match("Hello, world.",/o/)
    print RSTART, RLENGTH
}

4.split(string,array,seperator)
该函数的功能是将一个字符串根据指定的分隔符拆分成一个数组。
其中第1个参数为要拆分的字符串,第2个参数是用来存储拆分结果的数组,第3个参数用来指定分隔符,分隔符可以使用正则表达式来表达。

#! /bin/awk -f
BEGIN {
    string="5P12p89"
    #使用分隔符P或者p分隔字符串
    split(string,arr,/[Pp]/)
    #输出第1~3个数组元素
    print arr[1]
    print arr[2]
    print arr[3]
}

5.sub(regexp,replacement,string)和gsub(regexp,replacement,string)
这2个函数的作用都是替换字符串中的子串,其区别在于前者只替换第1次出现的子串,而后者则替换所有出现的子串。
这2个函数的参数完全相同,第1个参数为正则表达式,表示匹配规则。第2个参数为用来替换的字符串,第3个参数是将要被处理的字符串。

#! /bin/awk -f
BEGIN {
    #定义字符串
    string="abcd6b12abcabc212@123465"
    #将第1个符合正则表达式/(abc)+[0-9]*/的子串用括号括起来
    sub(/(abc)+[0-9]*/,"(&)",string)
    print string
    #将所有符合正则表达式/(abc)+[0-9]*/的子串用括号括起来
    gsub(/(abc)+[0-9]*/,"(&)",string)
    print string
}

6.substr(string,start,[length])
该函数的功能是截取指定长度的子串。
第1个参数为父串,第2个参数表示子串开始截取的位置,第3个参数表示要截取的长度。其中,第3个参数可以省略,如果省略了该参数,则表示从start参数指定的位置开始,一直截取到父串的末尾。
通过match()函数和substr()函数,用户可以将父串中所有符合规则的子串提取出来。

#! /bin/awk -f
BEGIN {
    #定义字符串变量
    pages="p12-P34 P56-p78"
    #通过循环依次匹配字符串中的数字
    while(match(pages,/[0-9]+/)>0) {
    #截取并输出匹配的子串
        print substr(pages,RSTART,RLENGTH)
        #删除匹配的子串
        sub(/[0-9]+/,"",pages)                                     
    }
}

11.5.2  算术函数
awk提供了基本的执行算术运算的函数
int(x)   返回数值x的整数部分
sqrt(x)  返回数值x的平方根
exp(x)   返回e的x次方
log(x)   返回以e为底x的对数
sin(x)   返回x的正弦值
cos(x)   返回x的余弦值
rand()   返回介于0和1之间的随机数
srand([x]) 以x为种子返回一个随机数

11.6  数组
用户可以在awk编程环境中使用数组。这种特性使得用户在存储结构化的数据时变得非常方便。与其他的程序设计语言相比,awk中的数组有许多特殊的使用方法,本节将对这些使用方法进行详细介绍。

11.6.1  数组的定义和赋值
数组是用来存储一组相互关联的数据的结构体。在awk中,用户可以自定义数组,并且在定义数组时,毋需指定其类型和大小。
数组元素赋值的语法如下:
array[n]=value
其中,array表示数组名称,n表示数组元素的下标,等号为赋值运算符,value为要赋给数组元素的数值。
用户可以使用以下语法引用数组元素的值:
array[n]
其中,array表示数组名称,n为数组元素的下标。

#! /bin/awk -f
BEGIN {
    #为数组元素赋值
    arr[1]="Tim"
    arr["a"]=12
    arr[3]=3.1415
    arr[4]=5
    #输出数组元素的值
    print arr[1],arr[2],arr["a"]*arr[3],arr[4]
}

11.6.2  遍历数组
所谓数组的遍历,是指将数组中的每个元素的值依次输出。
当然,用户可以通过循环结构来实现数组的遍历。
在使用正常的循环结构来遍历数组时,必须首先知道数组的长度,这样的话才能确定循环终止的条件。
在awk中,数组的长度可以使用length()函数获得,该函数以数组名作为参数,返回数组的长度。

#! /bin/awk -f
BEGIN {
    #定义数组
    stu[1]="200200110"
    stu[2]="200200164"
    stu[3]="200200167"
    stu[4]="200200168"
    stu[5]="200200172"
    #计算数组的长度
    len=length(stu)
    #通过循环遍历数组
    for(i=1;i<=len;i++)
    {
        print i,stu[i]
    }
}

#! /bin/awk -f
BEGIN {
    #定义数组
    arr[1]="Tim"
    arr[2]="John"
    arr["a"]=12
    arr[3]=3.1415
    arr[4]=5
    arr[99]=23
    #遍历数组
    for(n in arr)
    {
        print arr[n]
    }
}

11.7  流程控制
作为一种程序设计语言,awk支持程序的流程控制,例如条件判断、循环以及其他的一些流程控制语句,例如continue、break以及exit等。掌握这些基本的流程控制语句,对于编写出结构良好的程序非常重要。本节将介绍awk流程控制语句的使用方法。

11.7.1  if语句
if语句的功能是根据用户指定的条件来决定执行程序的哪个分支,其语法如下:
if (expression){
    statement1
    statement2
}else {
    statement3
    statement4
}

#! /bin/awk -f
{
    #90分以上为A
    if ($2 >= 90) {
        print $1,"A"      
    } else {
        #80分以上为B
        if($2 >= 80 && $2 < 90){
            print $1,"B"
        }
        #其余为C
        else
        {
            print $1,"C"
        }                                   
    }
}

11.7.2  while语句
while语句是另外一种常用的循环结构,其语法如下:
while (expression)
{
    statement1
    statement2
    ...
}
当表达式expression的值为真时,执行循环体中的statement1以及statement2等语句。如果循环体中只包含一条语句,则可以省略大括号。

#! /bin/awk -f
BEGIN {
    #定义循环变量
    i=0
    #while循环开始
    while (++i <= 9)
    {
        #输出循环变量i的平方
        print i^2
    }
}

11.7.3  do…while语句
awk还支持另外一种while循环语句,其语法如下:
do {
    statement1
    statement2
    ...
} while (expression)

同样,当表达式expression的值为真时执行循环体中的语句。

#! /bin/awk -f
BEGIN {
    #定义循环变量
    i=1
    do {
        #输出循环变量的平方
        print i^2
    } while (++i<=9)
}

11.7.4  for语句
for循环语句通常用在循环次数已知的场合中,其语法如下:
for(expression1; expression2; expression3)
{
    statement1
    statement2
    ...
}
在上面的语法中,表达式expression1通常用来初始化循环变量,表达式expression2通常用来指定循环执行的条件,表达式expression3通常用来改变循环变量的值。当表达式expression2的值为真时,执行循环体中的语句。

#! /bin/awk -f
BEGIN {
    #外层循环
    for(i=1;i<=9;i++)
    {
        #内层循环
        for(j=1;j<=i;j++)
        {
            #将每一行的数值连接成一个字符串
            if(i*j<10)
            {
                row=row"   "i*j
            }
            else
            {
                row=row"  "i*j
            }
        }
        #输出每一行数值
        print row
        row=""
    }
}

11.7.5  break语句
用户可以通过使用break语句在适当的时机退出for以及while等循环结构,用来退出循环结构,而不必等到循环结构自己退出。

#! /bin/awk -f
BEGIN {
    #循环读取数据
    while( getline < "scores.txt" > 0 )
    {
        #当第1个字段的额值为Kity时退出
        if($1=="Kity")
            break
        else
            print $1,$2,$3,$4,$5                                                 }
}

11.7.6  continue语句
continue语句的主要功能是跳过循环结构中该语句后面的尚未执行的语句。break语句与continue语句的功能有着明显的区别,前者是直接退出循环结构,而后者是跳过循环体中尚未执行的语句,重新执行下一次循环。

#! /bin/awk -f
BEGIN {
    #通过循环读取数据
    while( getline < "scores.txt" > 0 )
    {
        #当第1个字段含有字符串Nancy时跳过后面的语句
        if($1 == "Kity")
            continue
        print $1,$2,$3,$4,$5
    }
}

11.7.7  next语句
next语句的功能与continue语句非常相似,但是next语句并不是用在循环结构中,而是用在整个akw程序中。当awk执行程序时,如果遇到next语句,则该语句后面的所有的程序语句都被忽略,包括其他的模式以及对应的操作。awk会继续读取下一行数据,并且从第一个模式及其操作开始执行。

#! /bin/awk -f
#当读取的行为空行时跳过后面的语句
/^[\t]*$/ {
    next
}

#输出各个字段
{
    print $1,$2,$3,$4,$5

}

11.7.8  exit语句
exit语句的功能是终止awk程序的执行。

11.8  awk程序的格式化输出
对于程序来说,输出是一项非常重要的功能。而绝大部分的用户对于数据输出都有一定的格式要求。awk提供了基本的格式化输出功能,本节将介绍awk中与输出有关的函数。

11.8.1  基本print语句
print语句提供了基本的输出功能。我们在前面许多例子中,已经使用该语句来输出各种数据。print语句的基本语法如下:
print string1,string2,...
在上面的语法中,参数string1以及string2等是要输出的数据,各个参数之间使用逗号隔开。在输出的时候,print语句会自动使用空格将各个参数值隔开。

11.8.2  格式化输出printf语句
虽然大多数情况下awk的print语句可以完成任务,但有时我们还需要对格式做更多的控制。awk提供了printf函数来实现字符串的格式化。这个函数的功能和语法与C语言中的printf()函数基本相同,如下:
printf(format, [arguments])
其中圆括号是可选的,第1个参数format是一个用来描述输出格式的字符串,通常以引号括起来的字符串常量的形式提供。arguments为一个参数列表,表示用来显示的数据,可以是变量名等,多个参数之间用逗号隔开。参数列表的项是有顺序的,与前面的格式化字符串中的格式说明相对应。
格式化字符串的语法如下:
%format

#! /bin/awk -f

{
    printf("%s\t%d\t%d\t%d\t%d\t%d\n",$1,$2,$3,$4,$5,($2 + $3 + $4 + $5))
}

11.8.3  使用sprintf()函数生成格式化字符串
sprintf函数的功能与printf函数的功能大致相同,但是该函数只是以字符串的形式返回格式化结果,并不输出到标准输出设备。用户可以将格式化的结果进行其他的处理或者使用print和printf函数输出到标准输出。

#! /bin/awk -f
BEGIN {
    print "Scores list"
}

{
    printf ("%s\t%d\t%d\t%d\t%d\t%d\n",$1,$2,$3,$4,$5,($2 + $3 + $4 + $5))
    total+=$2 + $3 + $4 + $5
}

END {
    average=total/NR
    sum=sprintf("Total: %d students, average: %.2f",NR,average)
    print sum
}

11.9  awk的程序与Shell的交互
awk提供了与Shell命令交互的能力,从而可以使得用户在awk程序中使用系统资源。awk主要通过2种机制来实现这种交互功能,分别为管道和Sytem函数。本节将对这2种交互机制进行详细介绍。

11.9.1  通过管道实现与Shell的交换
用户可以很容易地在awk程序中使用操作系统资源,包括在程序中调用Shell命令处理程序中的数据;或者在awk程序中获取Shell命令的执行结果。awk提供了管道来实现这种数据的双向交互。awk的管道与UNIX或者Linux中的管道非常相似,但是特性有些不同。

#! /bin/awk -f
BEGIN {
    while("who" | getline) n++
    printf("There %d online users.\n",n)
}

11.9.2  通过system函数实现与Shell的交互
awk提供另一个调用Shell命令的方法, 即使用awk函数,其语法如下:
system(command)
其中参数command表示要执行的Shell命令。与管道相比,system函数有许多据局限,例如不能在awk程序中直接获取Shell命令的执行结果,另外,也不能直接将awk程序中的数据传递给Shell命令来处理。要实现这种数据传递,必须借助其他的的一些手段。

#! /bin/awk -f
BEGIN {
    system("ls > filelist")
    
    while(getline < "filelist" > 0)
    {
        print $1
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值