Awk命令入门教程详解

发布时间:2020-03-07编辑:脚本学堂
awk命令的入门教程,awk命令的基本语法,包括了awk外部脚本、awk正则表达式与块、awk条件语句、awk字段分隔符、awk记录号等内容。

第一个linuxjishu/13830.html target=_blank class=infotextkey>awk

代码 1.1: 第一个awk
 

$ awk '{ print }' /etc/passwd


您将会见到/etc/passwd文件的内容出现在眼前。现在,解释awk做了些什么。调用awk时,我们指定/etc/passwd作为输入文件。执行awk时,它依次对/etc/passwd中的每一行执行print命令。所有输出都发送到stdout,所得到的结果与与执行cat /etc/passwd完全相同。

现在,解释{ print }代码块。在awk中,花括号用于将几块代码组合到一起,这一点类似于C语言。在代码块中只有一条print命令。在awk中,如果只出现print命令,那么将打印当前行的全部内容。

代码 1.2: 屏显当前行
 

$ awk '{ print $0 }' /etc/passwd
$ awk '{ print "" }' /etc/passwd


在awk中,$0变量表示整个当前行,所以print和print $0的作用完全一样。

代码 1.3: 用一些文字把屏幕填满
$ awk '{ print "hiya" }' /etc/passwd

一、多个字段

代码 1.4: print $1
 

复制代码 代码示例:
$ awk -F":" '{ print $1 $3 }' /etc/passwd
halt7
operator11
root0
shutdown6
sync5
bin1
....etc.

代码 1.5: print $1 $3
 

$ awk -F":" '{ print $1 " " $3 }' /etc/passwd

代码 1.6: $1$3
 

复制代码 代码示例:
$ awk -F":" '{ print "username: " $1 "ttuid:" $3 }' /etc/passwd
username: halt          uid:7
username: operator      uid:11
username: root          uid:0
username: shutdown      uid:6
username: sync          uid:5
username: bin           uid:1
....etc.

二、外部脚本

代码 1.7: 示例脚本
 

复制代码 代码示例:
BEGIN { FS=":" }
{ print $1 }


这两个方法的差别在于如何设置字段分隔符。在这个脚本中,字段分隔符在代码自身中指定(通过设置FS变量),而在前一个示例中,通过在命令行上向awk传递-F":"选项来设置FS。通常,最好在脚本自身中设置字段分隔符,只是因为这表示您可以少输入一个命令行自变量。我们将在本文的后面详细讨论FS变量。

三、BEGIN和END块

通常,对于每个输入行,awk都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在awk开始处理输入文件中的文本之前执行初始化代码。对于这种情况,awk允许您定义一个BEGIN块。我们在前一个示例中使用了BEGIN块。因为awk在开始处理输入文件之前会执行BEGIN块,因此它是初始化FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。

awk还提供了另一个特殊块,叫作END块。awk在处理了输入文件中的所有行之后执行这个块。通常,END块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

四、正则表达式和块

代码 1.8: 正则表达式和块
 

/foo/ { print }
/[0-9]+.[0-9]*/ { print }

五、表达式和块

代码 1.9: fredprint
$1 == "fred" { print $3 }
代码 1.10: root
$5 ~ /root/ { print $3 }

六、条件语句

代码 1.11: if
 

复制代码 代码示例:
{
    if ( $5 ~ /root/ ) {
        print $3
    }
}
 

这两个脚本的功能完全一样。第一个示例中,布尔表达式放在代码块外面。而在第二个示例中,将对每一个输入行执行代码块,而且我们使用if语句来选择执行print命令。这两个方法都可以使用,可以选择最适合脚本其它部分的一种方法。

代码 1.12: if if
 

复制代码 代码示例:
{
    if ( $1 == "foo" ) {
        if ( $2 == "foo" ) {
            print "uno"
        } else {
            print "one"
        }
    } else if ($1 == "bar" ) {
        print "two"
    } else {
        print "three"
    }
}

代码 1.13: if
 

复制代码 代码示例:
! /matchme/ { print $1 $3 $4 }

代码 1.14: if
 

复制代码 代码示例:
{
    if ( $0 !~ /matchme/ ) {
        print $1 $3 $4
    }
}
 

这两个脚本都只输出不包含matchme字符序列的那些行。此外,还可以选择最适合您的代码的方法。它们的功能完全相同。

代码 1.15: 打印字段等于foo且等于bar的行
 

复制代码 代码示例:
( $1 == "foo" ) && ( $2 == "bar" ) { print }


这个示例只打印第一个字段等于foo且第二个字段等于bar的那些行。

七、数值变量!

在BEGIN块中,将整数变量x初始化成零。然后,awk每次遇到空白行时,awk将执行x=x+1语句,递增x。处理完所有行之后,执行END块,awk将打印出最终摘要,指出它找到的空白行数量。

八、字符串化的变量

代码 1.16: 示例字段
2.01
代码 1.17: 1.01x$( )1.01
{ print ($1^2)+1 }
如果做一个小实验,就可以发现如果某个特定变量不包含有效数字,awk在对数学表达式求值时会将该变量当作数字零处理。

九、众多的运算符

awk的另一个优点是它有完整的数学运算符集合。除了标准的加、减、乘、除,awk还允许使用前面演示过的指数运算符“^”、模(余数)运算符“%”和其它许多从C语言中借入的易于使用的赋值操作符。

这些运算符包括前后加减( i++ 、 --foo )、加/减/乘/除赋值运算符( a+=3 、 b*=2 、 c/=2.2 、 d-=6.2 )。不仅如此──我们还有易于使用的模/指数赋值运算符( a^=2 、 b%=4 )。

十、字段分隔符

awk有它自己的特殊变量集合。其中一些允许调整awk的运行方式,而其它变量可以被读取以收集关于输入的有用信息。我们已经接触过这些特殊变量中的一个,FS。前面已经提到过,这个变量让您可以设置awk要查找的字段之间的字符序列。我们使用/etc/passwd作为输入时,将FS设置成":"。当这样做有问题时,我们还可以更灵活地使用FS。

代码 1.18: 另一个字段分隔符
 

FS="t+"


以上示例中,我们使用特殊 "+" 规则表达式字符,它表示“一个或多个前一字符”。

代码 1.19: 将FS设置成space
 

FS="[[:space:]+]"


这个赋值表达式也有问题,它并非必要。为什么?因为缺省情况下,FS设置成单一空格字符,awk将这解释成表示“一个或多个空格或tab”。在这个特殊示例中,缺省FS设置恰恰是您最想要的!

代码 1.20: 字段分隔符示例
 

FS="foo[0-9][0-9][0-9]"

十一、字段数量

代码 1.21: 字段数量
 

{
    if ( NF > 2 ) {
        print $1 " " $2 ":" $3
    }
}

十二、记录号

代码 1.22: 记录号
 

{
    #skip header
    if ( NR > 10 ) {
        print "ok, now for the real information!"
    }
}
 

awk提供了适合各种用途的附加变量,以后探讨。