如何在 Linux 中使用 AWK 语言操作文本

介绍

Linux 实用程序通常遵循 Unix 设计哲学。 鼓励工具小,使用简单的文本文件输入和输出,并以模块化方式运作. 由于这种遗产,我们有很好的文本处理功能,使用工具如 sedawk

「awk」是一種程式語言和文本處理器,您可以用來以非常有用的方式操縱文本資料. 在本指南中,您將探索如何使用「awk」命令行工具以及如何使用它來處理文本。

基本语法

awk命令默认包含在所有现代Linux系统中,因此您不需要安装它才能开始使用。

「awk」在处理以可预测的方式格式化的文本文件时最有用,例如,它擅长解析和操纵表数据。

默认情况下,它使用白色空间(空间,标签等)来分离字段. 幸运的是,Linux系统上的许多配置文件都使用这种格式。

awk命令的基本格式是:

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

您可以从任何awk命令中忽略搜索部分或行动部分。默认情况下,如果没有给出的行动部分,所采取的行动是打印

如果没有给出搜索部分,则awk执行每个行上列出的操作。

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

在其最简单的形式中,您可以使用awk,如cat,将文本文件的所有行打印到屏幕上。

创建一个favorite_food.txt文件,列出一组朋友最喜欢的食物:

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

现在使用awk命令将文件打印到屏幕上:

1awk '{print}' favorite_food.txt

您将看到在屏幕上打印的文件:

1[secondary_label Output]
2carrot sandy
3wasabi luke
4sandwich brian
5salad ryan
6spaghetti jessica

让我们试试awk的搜索过滤功能,通过搜索文件的文本沙子:

1awk '/sand/' favorite_food.txt
1[secondary_label Output]
2carrot sandy
3sandwich brian

正如你所看到的,awk现在只打印有字符的行。

使用常规表达式,您可以瞄准文本的特定部分. 若要显示仅以字母开头的行,请使用常规表达式 ^沙:

1awk '/^sand/' favorite_food.txt

这一次,只显示一行:

1[secondary_label Output]
2sandwich brian

同样,您可以使用操作部分来指定要打印的信息片段,例如,若要打印只有第一列,请使用以下命令:

1awk '/^sand/ {print $1;}' favorite_food.txt
1[secondary_label Output]
2sandwich

例如,第一个列是$1,第二个列是$2,您可以用$0引用整个行。

内部变量和扩展格式

awk命令使用一些内部变量来分配某些信息,当它处理一个文件。

awk使用的内部变量是:


您可以随意更改这些变量的值,以匹配您的文件的需求. 通常,您会在处理的初始化阶段这样做。

这个awk语法比你迄今所使用的更为复杂,还有可选的BEGINEND块,可以分别包含在文件处理之前和之后执行的命令。

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

1awk 'BEGIN { action; }
2/search/ { action; }
3END { action; }' input_file

BEGINEND关键字是特定条件集,就像搜索参数一样。

这意味着您可以在开始部分中更改一些内部变量,例如/etc/passwd文件由列(:)而不是白空间划界。

要打印此文件的第一列,请执行以下命令:

1awk 'BEGIN { FS=":"; }
2{ print $1; }' /etc/passwd
1[secondary_label Output]
2root
3daemon
4bin
5sys
6sync
7games
8man
9. . .

您可以使用开始结束块来打印您正在打印的字段的信息. 使用以下命令将文件中的数据转换为表,与使用\t的标签保持良好间隔:

1awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
2{print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
3END { print "---------\nFile Complete" }' /etc/passwd

你会看到这个输出:

 1[secondary_label Output]
 2User		UID		GID		Home		Shell
 3--------------
 4root 		 0 		 0 		 /root 		 /bin/bash
 5daemon 		 1 		 1 		 /usr/sbin 		 /bin/sh
 6bin 		 2 		 2 		 /bin 		 /bin/sh
 7sys 		 3 		 3 		 /dev 		 /bin/sh
 8sync 		 4 		 65534 		 /bin 		 /bin/sync
 9. . .
10---------
11File Complete

正如您所看到的,您可以通过利用awk的一些功能来格式化事物。

每个扩展的部分都是可选的,事实上,如果定义了另一个部分,主要的操作部分本身都是可选的。

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

你会看到这个输出:

1[secondary_label Output]
2We can use awk like the echo command

现在让我们看看如何在输出中的字段中搜索文本。

域搜索和复合表达式

在前面的一個例子中,您在「favorite_food.txt」檔案中打印了行,它以「沙子」開始。

如果你想知道搜索模式是否匹配 field 的开始?

创建favorite_food.txt文件的新版本,在每个人的食物前面添加一个项目号码:

1echo "1 carrot sandy
22 wasabi luke
33 sandwich brian
44 salad ryan
55 spaghetti jessica" > favorite_food.txt

如果你想从这个文件中找到所有开始sa的食物,你可以开始尝试这样的东西:

1awk '/sa/' favorite_food.txt

这显示了包含sa的所有行:

1[secondary_label Output]
21 carrot sandy
32 wasabi luke
43 sandwich brian
54 salad ryan

在这里,你会匹配字中任何sa的实例,这最终会包括中间有模式的wasabi或不是你想要的列的sandy等东西,在这种情况下,你只对字 beginningsecond 列中的sa感兴趣。

您可以使用此命令说awk仅匹配第二列的开始:

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

正如你所看到的,这只允许我们在第二列开始时搜索匹配。

field_num ~部分规定awk只应注意第二列。

1[secondary_label Output]
23 sandwich brian
34 salad ryan

您可以通过在 tilde (~) 之前添加!字符来轻松搜索 not 匹配的东西。

1awk '$2 !~ /^sa/' favorite_food.txt
1[secondary_label Output]
21 carrot sandy
32 wasabi luke
45 spaghetti jessica

如果您稍后决定,您只对不以sa开头的行感兴趣,并且项目数小于5,您可以使用这样的复合表达式:

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

这引入了一些新概念. 第一种是使用&&运算符来添加对匹配的行额外要求的能力. 使用此方法,您可以将对匹配的行任意数量的条件组合在一起。

你会看到这个输出:

1[secondary_label Output]
21 carrot sandy
32 wasabi luke

您可以使用awk来处理文件,但您也可以使用其他程序的输出。

处理其他程序的输出

您可以使用awk命令来解析其他程序的输出,而不是指定文件名,例如,您可以使用awk来解析ip命令中的IPv4地址。

ip a 命令显示您的计算机上的所有网络接口的 IP 地址、广播地址和其他信息. 若要显示名为 eth0 的接口信息,请使用以下命令:

1ip a s eth0

你会看到以下结果:

1[secondary_label Output]
22571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
3    link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
4    inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0
5       valid_lft forever preferred_lft forever

您可以使用awk来瞄准inet行,然后只打印 IP 地址:

1ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'

「-F」旗表示「awk」用正規表現「[/ ]+」來界定前方的切片或空格。這將線「net 172.17.0.11/16」分成不同的字段。 IP 地址位於第三個字段,因為行開始的空格也算作一個字段,因為你被界定為空格和空格。 請注意,在這種情況下,「awk」將連續的空格當作一個單一空間。

输出显示 IP 地址:

1[secondary_label Output]
2172.17.0.11

您将找到许多地方,您可以使用awk来搜索或解析其他命令的输出。

结论

到目前为止,您应该对如何使用awk命令来操纵、格式化和选择性地打印文本文件和文本流有基本的了解。

要了解更多关于awk的信息,你可以阅读它的创作者(https://ia902309.us.archive.org/25/items/pdfy-MgN0H1joIoDVoIC7/The_AWK_Programming_Language.pdf)的免费公共领域书籍,它深入了解更多细节。

Published At
Categories with 技术
comments powered by Disqus