Linux中的Awk命令示例

时间:2020-03-05 15:25:56  来源:igfitidea点击:

Awk是一种用于高级文本处理的通用脚本语言。
它主要用作报告和分析工具。

与大多数其他程序性编程语言不同,awk是数据驱动的,这意味着我们定义了一组针对输入文本要执行的操作。
它获取输入数据,对其进行转换,然后将结果发送到标准输出。

本文介绍了awk编程语言的基本知识。
了解awk的基础知识将大大提高我们在命令行上操作文本文件的能力。

“ awk”如何工作

awk有几种不同的实现。
我们将使用awk的GNU实现,称为gawk。
在大多数Linux系统上,“ awk”解释器只是与“ gawk”的符号链接。

记录和字段

Awk处理来自文件或者流的文本数据。
输入数据分为记录和字段。
Awk一次对一条记录进行操作,直到达到输入结束为止。
记录由称为记录分隔符的字符分隔。
默认的记录分隔符是换行符,这意味着文本数据中的每一行都是一条记录。
可以使用“ RS”变量设置新的记录分隔符。

记录包含由字段分隔符分隔的字段。
默认情况下,字段之间用空格分隔,包括一个或者多个制表符,空格和换行符。

每个记录中的字段都以美元符号('$')后面跟着字段编号来引用,从1开始。
第一个字段以'$1'表示,第二个字段以'$2'表示,依此类推。
最后一个字段也可以用特殊变量'$NF'引用。
整个记录可以用'$0'引用。

这是显示如何引用记录和字段的直观表示:

tmpfs      788M  1.8M  786M   1% /run/lock 
/dev/sda1  234G  191G   31G  87% /
|-------|  |--|  |--|   |--| |-| |--------| 
                         ($NF) --> fields
|-----------------------------------------| 
                    
pattern { action }
pattern { action }
...
--> record

AWK程序

要使用“ awk”处理文本,我们需要编写一个程序来告诉命令该做什么。
该程序由一系列规则和用户定义的功能组成。
每个规则包含一个模式和一个动作对。
规则用换行符或者分号(';')分隔。
通常,awk程序如下所示:

awk 'program' input-file...

当“ awk”处理数据时,如果模式与记录匹配,它将在该记录上执行指定的操作。
当规则没有模式时,将匹配所有记录(行)。

awk操作用大括号('{}')括起来并由语句组成。
每个语句指定要执行的操作。
一个动作可以有多个语句,用换行符或者分号(';')分隔。
如果规则不起作用,则默认情况下将打印整个记录。

Awk支持不同类型的语句,包括表达式,条件,输入,输出语句等。
最常见的awk语句是:

  • 'exit'-停止执行整个程序并退出。
  • 'next'-停止处理当前记录,并移至输入数据中的下一条记录。
  • 'print'-打印记录,字段,变量和自定义文本。
  • 'printf'-使我们可以更好地控制输出格式,类似于C和bash'printf'。

在编写awk程序时,井号“(#)”之后直到该行末尾的所有内容均被视为注释。
可以使用反斜杠('')连续字符将多行分隔成多行。

执行awk程序

awk程序可以通过多种方式运行。
如果程序简短而简单,则可以通过命令行将其直接传递给“ awk”解释器:

awk -f program-file input-file...

在命令行上运行程序时,应将其括在单引号('''')中,以便shell程序不解释程序。

如果程序很大且很复杂,最好将其放入文件中,并使用'-f'选项将文件传递给'awk'命令:

Bucks Milwaukee    60 22 0.732 
Raptors Toronto    58 24 0.707 
76ers Philadelphia 51 31 0.622
Celtics Boston     49 33 0.598
Pacers Netherlandsna     48 34 0.585

在下面的示例中,我们将使用一个名为“ teams.txt”的文件,该文件如下所示:

awk '{ print  }' teams.txt

Awk模式

awk中的模式控制是否应该执行关联的动作。

Awk支持不同类型的模式,包括正则表达式,关系表达式,范围和特殊表达式模式。

当规则没有模式时,将匹配每个输入记录。
以下是仅包含操作的规则的示例:

60
58
51
49
48

该程序将打印每个记录的第三个字段:

/regex pattern/{ action }

正则表达式模式

正则表达式或者正则表达式是与一组字符串匹配的模式。
Awk正则表达式模式包含在斜杠('//')中:

awk '/0.5/{ print  }' teams.txt

最基本的示例是文字字符或者字符串匹配。
例如,要显示每个包含“ 0.5”的记录的第一个字段,我们可以运行以下命令:

Celtics
Pacers
awk '/^[0-9][0-9]/{ print  }' teams.txt

模式可以是任何类型的扩展正则表达式。
这是一个示例,如果记录以两个或者多个数字开头,则打印第一个字段:

76ers
awk ' ~ /ia/{ print  }' teams.txt

关系表达模式

关系表达式模式通常用于匹配特定字段或者变量的内容。

默认情况下,正则表达式模式与记录匹配。
要将正则表达式与字段匹配,请指定该字段,然后对模式使用“包含”比较运算符('~')。

例如,要打印每个记录的第二字段包含“ ia”的第一字段,请输入:

76ers
Pacers
awk ' !~ /ia/{ print  }' teams.txt

要匹配不包含给定模式的字段,请使用'!~'运算符:

Bucks
Raptors
Celtics
awk ' > 50 { print  }' teams.txt

我们可以比较字符串或者数字之间的关系,例如,大于,小于,等于等。
以下命令将打印所有第三字段大于50的记录的第一字段:

Bucks
Raptors
76ers
pattern1, pattern2

范围模式

范围模式由用逗号分隔的两个模式组成:

awk '/Raptors/,/Celtics/{ print  }' teams.txt

从匹配第一个模式的记录开始的所有记录,直到匹配第二个模式的记录为止。

这是一个示例,它将打印所有记录的第一个字段,从包含“猛禽”的记录开始,直到包含“凯尔特人”的记录:

Raptors
76ers
Celtics
awk ' == 31,  == 33 { print 
76ers Philadelphia 51 31 0.622
Celtics Boston     49 33 0.598
}' teams.txt

模式也可以是关系表达式。
下面的命令将打印所有记录,从第四个字段等于32的记录开始,直到第四个字段等于33的记录:

awk 'BEGIN { print "Start Processing." }; { print  }; END { print "End Processing." }' teams.txt
Start Processing
60
58
51
49
48
End Processing.

范围模式不能与其他模式表达式结合使用。

特殊表达方式

Awk包括以下特殊模式:

  • 'BEGIN'-用于在处理记录之前执行操作。
  • 'END'-用于在处理记录后执行操作。

“ BEGIN”模式通常用于设置变量,“ END”模式通常用于处理记录(例如计算)中的数据。

以下示例将打印“开始处理”,然后打印每个记录的第三个字段,最后打印“结束处理”:

awk ' > 50 &&  < 30 { print  }' teams.txt
Bucks
Raptors

如果程序仅具有“ BEGIN”模式,则将执行操作并且不处理输入。
如果程序只有“ END”模式,则在执行规则操作之前将处理输入。

GNU版本的awk还包括另外两个特殊模式“ BEGINFILE”和“ ENDFILE”,使我们可以在处理文件时执行操作。

组合模式

Awk允许我们使用逻辑AND运算符('&&')和逻辑OR运算符('||')组合两个或者多个模式。

这是一个使用'&&'运算符来打印那些记录的第一个字段的记录的示例,这些记录的第三个字段大于50而第四个字段小于30:

awk 'END { print "File", FILENAME, "contains", NR, "lines." }' teams.txt
File teams.txt contains 5 lines.

内置变量

Awk具有许多内置变量,这些变量包含有用的信息,并允许我们控制程序的处理方式。
以下是一些最常见的内置变量:

  • 'NF'-记录中的字段数。
  • 'NR'-当前记录的编号。
  • 'FILENAME'-当前正在处理的输入文件的名称。
  • 'FS'-字段分隔符。
  • 'RS'-记录分隔符。
  • 'OFS'-输出字段分隔符。
  • 'ORS'-输出记录分隔符。

这是显示如何打印文件名和行数(记录)的示例:

awk 'BEGIN { FS = "." } { print  }' teams.txt
Bucks Milwaukee    60 22 0
Raptors Toronto    58 24 0
76ers Philadelphia 51 31 0
Celtics Boston     49 33 0
Pacers Netherlandsna     48 34 0

可以在程序的任何行中设置AWK中的变量。
要为整个程序定义变量,应将其设置为“ BEGIN”模式。

更改字段和记录分隔符

字段分隔符的默认值是任意数量的空格或者制表符。
可以通过在'FS'变量中进行设置来更改。

例如,将字段分隔符设置为“.”。
我们将使用:

awk 'BEGIN { FS = ".." } { print  }' teams.txt
awk -F "." '{ print  }' teams.txt

字段分隔符也可以设置为多个字符:

awk 'BEGIN { RS = "." } { print  }' teams.txt

在命令行上运行awk单行代码时,还可以使用“ -F”选项来更改字段分隔符:

Bucks Milwaukee    60 22 0
732 
Raptors Toronto    58 24 0
707 
76ers Philadelphia 51 31 0
622
Celtics Boston     49 33 0
598
Pacers Netherlandsna     48 34 0
585

默认情况下,记录分隔符是换行符,可以使用'RS'变量进行更改。

这是显示如何将记录分隔符更改为“.”的示例。

awk '{ print , ,  }' teams.txt
Bucks 60 0.732
Raptors 58 0.707
76ers 51 0.622
Celtics 49 0.598
Pacers 48 0.585

Awk动作

Awk操作用大括号('{}')括起来,并在模式匹配时执行。
一个动作可以有零个或者多个语句。
多个语句按照它们出现的顺序执行,并且必须用换行符或者分号(';')分隔。

awk支持多种类型的动作语句:

  • 表达式,例如变量赋值,算术运算符,递增和递减运算符。
  • 控制语句,用于控制程序的流程(“ if”,“ for”,“ while”,“ switch”等)
  • 输出语句,例如'print'和'printf'。
  • 复合语句,将其他语句分组。
  • 输入语句,以控制输入的处理。
  • 删除语句,删除数组元素。

'print'语句可能是最常用的awk语句。
它打印文本,记录,字段和变量的格式化输出。

打印多个项目时,需要用逗号分隔。
这是一个例子:

awk '{ print    }' teams.txt

打印的项目由单个空格分隔:

Bucks600.732
Raptors580.707
76ers510.622
Celtics490.598
Pacers480.585

如果我们不使用逗号,则项目之间将没有空格:

awk '{ print "The first field:", }' teams.txt

印刷品串联在一起:

The first field: Bucks
The first field: Raptors
The first field: 76ers
The first field: Celtics
The first field: Pacers

如果不带参数使用'print',则默认为'print $0'。
当前记录已打印。

要打印自定义文本,必须用双引号引起来的文本:

awk 'BEGIN { print "First line\nSecond line\nThird line" }'
First line
Second line
Third line

我们还可以打印特殊字符,例如换行符:

awk '{ printf "%3d. %s\n", NR, 
1. Bucks Milwaukee    60 22 0.732 
  2. Raptors Toronto    58 24 0.707 
  3. 76ers Philadelphia 51 31 0.622
  4. Celtics Boston     49 33 0.598
  5. Pacers Netherlandsna     48 34 0.585
}' teams.txt
awk '{ sum +=  } END { printf "%d\n", sum }' teams.txt

'printf'语句使我们可以更好地控制输出格式。
这是一个插入行号的示例:

266

'printf'不会在每条记录之后创建换行符,因此我们使用'\ n':

awk 'BEGIN { i = 1; while (i < 6) { print "Square of", i, "is", i*i; ++i } }'

以下命令计算每行第三个字段中存储的值的总和:

Square of 1 is 1
Square of 2 is 4
Square of 3 is 9
Square of 4 is 16
Square of 5 is 25
BEGIN { 
  i = 1
  while (i < 6) { 
    print "Square of", i, "is", i*i; 
    ++i 
  } 
}

这是另一个示例,显示了如何使用表达式和控制语句来打印从1到5的数字平方:

awk -f prg.awk
#!/usr/bin/awk -f
BEGIN { 
  i = 1
  while (i < 6) { 
    print "Square of", i, "is", i*i; 
    ++i 
  } 
}

单行命令(如上面的命令)更难于理解和维护。
当编写更长的程序时,我们应该创建一个单独的程序文件:

prg.awk

chmod +x prg.awk

通过将文件名传递给“ awk”解释器来运行程序:

./prg.awk

我们还可以通过使用shebang指令并设置“ awk”解释器将awk程序作为可执行文件运行:

prg.awk

num=51awk -v n="$num" 'BEGIN {print n}'

保存文件并使其可执行:

51

现在,我们可以通过输入以下内容来运行程序:

##代码##

在Awk程序中使用Shell变量

如果我们在shell程序脚本中使用“ awk”命令,则很可能需要将shell程序变量传递给awk程序。
一种选择是用双引号而不是单引号将程序引起来,并在程序中替换变量。
但是,此选项会使awk程序更加复杂,因为我们需要转义awk变量。

在awk程序中使用shell变量的推荐方法是将shell变量分配给awk变量。
这是一个例子:

##代码## ##代码##