介绍
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语法实际上比我们最初显示的稍微复杂一些。 也有可选的BEGIN
和END
可以包含命令之前和之后的文件处理,分别执行块。
这使我们的扩展语法看起来像这样:
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版本。