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

介绍

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
赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏