如何使用AWK语言在Linux中处理文本

AWK是一种编程语言和工具包括在可用于操作和处理文本文件细粒度地对所有的Linux发行版。在本指南中,我们将讨论如何使用awk来有效地处理文本文件的基础知识。

介绍


Linux实用程序经常遵循Unix的设计理念。 鼓励工具小,使用纯文本文件进行输入和输出,并以模块化方式操作。 由于这种传统的,我们有一样的工具极大的文字处理功能的sed和awk。

在本指南中,我们将讨论awk。 Awk是一种编程语言和文本处理器,可用于以非常有用的方式处理文本数据。 我们将在Ubuntu 12.04 VPS上讨论这个问题,但它应该在任何现代Linux系统上运行。

基本语法


awk命令默认情况下,所有现代的Linux系统包括在内,所以我们并不需要安装它开始使用它。

Awk在处理以可预测的方式格式化的文本文件时最有用。 例如,它在解析和操纵表格数据方面表现优异。 它在逐行的基础上操作,并遍历整个文件。

默认情况下,它使用空格(空格,制表符等)分隔字段。 幸运的是,你的Linux系统上的许多配置文件都使用这种格式。

awk命令的基本格式是:

awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse

您可以从任何awk命令中省略搜索部分或操作部分。 默认情况下,如果未给出“动作”部分,则采取的操作为“打印”。 这只是打印所有匹配的行。

如果未给出搜索部分,awk将执行每行上列出的操作。

如果两者都给出,awk使用搜索部分来决定当前行是否反映该模式,然后对匹配执行操作。

简单用法


在最简单的形式中,我们可以用awk像cat只需打印文本文件的所有行输出到屏幕。

让我们打印出我们的服务器的fstab文件,它列出了它知道的文件系统:

awk '{print}' /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
#                
proc            /proc           proc    nodev,noexec,nosuid 0       0
# / was on /dev/vda1 during installation
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd /               ext4    noatime,errors=remount-ro 0       1

这不是很有用。 让我们试试awk的搜索过滤功能:

awk '/UUID/' /etc/fstab
# device; this may be used with UUID= as a more robust way to name devices
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd /               ext4    noatime,errors=remount-ro 0       1

如你所见,awk现在只打印其中有“UUID”的行。 我们可以通过指定UUID必须位于行的最开始部分来除去额外的注释行:

awk '/^UUID/' /etc/fstab
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd /               ext4    noatime,errors=remount-ro 0       1

同样,我们可以使用操作部分指定要打印的信息。 例如,要只打印第一列,我们可以键入:

awk '/^UUID/ {print $1;}' /etc/fstab
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd

我们可以通过与它们的列号相关联的变量来引用每个列(由空格分隔)。 第一列可以通过引用$1为实例。 整条生产线可以通过引用$0

Awk内部变量和扩展格式


Awk在处理文件时使用一些内部变量来分配某些信息。

awk使用的内部变量有:

  • 文件名 :参考当前输入文件。
  • FNR:参考电流相对于当前输入文件中的记录的数量。 例如,如果你有两个输入文件,这将告诉你每个文件的记录号,而不是一个总。
  • FS:用于表示在一个记录中的每个字段的当前字段分隔符。 默认情况下,它设置为空格。
  • NF:在当前记录的字段的数量。
  • NR:当前记录的数量。
  • OFS:字段分隔符为输出的数据。 默认情况下,它设置为空格。
  • ORS:记录分隔符为输出的数据。 默认情况下,这是一个换行符。
  • RS:用于输入文件来区分不同的记录的记录分隔符。 默认情况下,这是一个换行符。

我们可以随意更改这些变量的值以匹配我们文件的需要。 通常我们在awk处理的初始化阶段执行此操作。

这带给我们另一个重要的概念。 Awk语法实际上比我们最初显示的稍微复杂一些。 也有可选的BEGINEND可以包含命令之前和之后的文件处理,分别执行块。

这使我们的扩展语法看起来像这样:

awk 'BEGIN { action; }
/search/ { action; }
END { action; }' input_file

BEGIN和END关键字实际上只是特定的条件集,就像搜索参数一样。 它们在文档处理之前和之后匹配。

这意味着我们可以更改BEGIN部分中的一些内部变量。 例如, /etc/passwd的文件分隔用冒号(:)而不是空白。 如果我们想打印出这个文件的第一列,我们可以输入:

sudo awk 'BEGIN { FS=":"; }
{ print $1; }' /etc/passwd
root
daemon
bin
sys
sync
games
man
. . .

我们可以使用BEGIN和END块来打印有关我们正在打印的字段的简单信息:

sudo awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
{print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
END { print "---------\nFile Complete" }' /etc/passwd
User        UID     GID     Home        Shell
--------------
root         0       0       /root       /bin/bash
daemon       1       1       /usr/sbin       /bin/sh
bin          2       2       /bin        /bin/sh
sys          3       3       /dev        /bin/sh
sync         4       65534       /bin        /bin/sync
. . .
---------
File Complete

正如你所看到的,我们可以通过利用一些awk的功能来很好地格式化事情。

每个扩展部分是可选的。 事实上,如果定义了另一个段,主动作段本身是可选的。 我们可以这样做:

awk 'BEGIN { print "We can use awk like the echo command"; }'

We can use awk like the echo command

Awk字段搜索和复合表达式


在上面的例子之一,我们印在该行/etc/fstab的文件以“UUID”开始了。 这很容易,因为我们正在寻找整条线的开始。

如果我们想知道,如果一个搜索模式在一个领域 ,而不是一开始是否匹配?

我们可以创建一个favorite_food.txt文件,其中列出的项目数量和一群朋友的喜爱的食物:

echo "1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan
5 spaghetti jessica" > favorite_food.txt

如果我们想从这个文件中找到以“sa”开头的所有食物,我们可以尝试这样的:

awk '/sa/' favorite_food.txt

1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan

这里,我们匹配任何“sa”的实例。 这不包括在中间有模式的“wasabi”,或者不在我们想要的列中的“sandy”。 我们只是在与在第二列的“sa” 开头的单词感兴趣。

我们可以通过使用此命令告诉awk仅在第二列的开头匹配:

awk '$2 ~ /^sa/' favorite_food.txt

3 sandwich brian
4 salad ryan

正如你所看到的,这使我们只能在第二列的开头搜索匹配。

“^”字符告诉awk将其搜索限制在字段的开头。 “field_num〜”部分指定它应该只注意第二列。

我们可以很轻松地搜索的东西, 通过指定的“!” 字符前的波浪号(〜)。 此命令将返回没有以“sa”的启动食品的所有行:

awk '$2 !~ /^sa/' favorite_food.txt

1 carrot sandy
2 wasabi luke
5 spaghetti jessica

如果我们稍后决定,我们只对上面是真的行和项目号小于5的行感兴趣,我们可以使用这样的复合表达式:

awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt

这里介绍一些新的东西。 首先是增加额外的要求该行通过使用相匹配的能力&&运营商。 使用它,您可以组合任意数量的条件以匹配线。

我们使用此运算符添加第一列的值小于5的检查。

结论


现在,您应该对awk如何操作,格式化和有选择地打印文本文件有基本的了解。 Awk是一个更大的主题,但实际上是一个完整的编程语言,完成了变量赋值,控制结构,内置函数等等。 它可以在脚本中使用,以便以可靠的方式格式化文本。

要了解有关如何使用awk的更多信息,请查看awk的更好的在线资源,以及更相关的gawk,现代Linux发行版上的awk的GNU版本。

作者:Justin Ellingwood