网站搜索

如何使用 awk 和正则表达式过滤文件中的文本或字符串


当我们在 Unix/Linux 中运行某些命令来读取或编辑字符串或文件中的文本时,我们大多数时候会尝试将输出过滤到感兴趣的给定部分。这就是使用正则表达式派上用场的地方。

另请阅读: 10 个有用的 Linux 链接运算符及其实际示例

什么是正则表达式?

正则表达式可以定义为表示多个字符序列的字符串。关于正则表达式最重要的事情之一是它们允许您过滤命令或文件的输出、编辑文本或配置文件的一部分等等。

正则表达式的特点

正则表达式由以下部分组成:

  1. 普通字符,例如空格、下划线(_)、A-Z、a-z、0-9。
  2. 扩展为普通字符的元字符,包括:

    1. (.) 它匹配除换行符之外的任何单个字符。
    2. (*) 它匹配零个或多个其前面的直接字符。
    3. [character(s)] 它匹配character(s)中指定的任何一个字符,也可以使用连字符(-)来表示一系列字符,例如如 [a-f][1-5] 等。
    4. ^ 它匹配文件中行的开头。
    5. $ 匹配文件中的行尾。
    6. \ 它是一个转义字符。

为了过滤文本,必须使用文本过滤工具,例如awk。您可以将 awk 视为一种自己的编程语言。但对于本指南使用 awk 的范围,我们将把它作为一个简单的命令行过滤工具来介绍。

awk 的一般语法是:

awk 'script' filename

其中 'script' 是一组可以被 awk 理解并在文件 filename 上执行的命令。

它的工作原理是读取文件中的给定行,复制该行,然后执行该行上的脚本。文件中的所有行都会重复此操作。

'script' 的格式为 '/pattern/ action',其中 pattern 是正则表达式,action 是 awk 在一行中找到给定模式时将执行的操作。

如何在Linux中使用awk过滤工具

在下面的示例中,我们将重点关注上面在 awk 特性下讨论的元字符。

使用 awk 的简单示例:

由于没有给出模式,下面的示例打印文件 /etc/hosts 中的所有行。

awk '//{print}'/etc/hosts

将 Awk 与模式结合使用:

在下面的示例中,已经给出了模式 localhost,因此 awk 将匹配 /etc/hosts 文件中具有 localhost 的行。

awk '/localhost/{print}' /etc/hosts 

在模式中使用带有 (.) 通配符的 Awk

在下面的示例中,(.) 将匹配包含 loclocalhostlocalnet 的字符串。

也就是说* l some_single_character c *

awk '/l.c/{print}' /etc/hosts

在模式中使用带有 (*) 字符的 awk

它将匹配包含 localhostlocalnetlinescapable 的字符串,如下例所示:

awk '/l*c/{print}' /etc/localhost

您还将意识到 (*) 试图为您提供它可以检测到的最长匹配项。

让我们看一个演示这一点的案例,采用正则表达式 t*t ,它表示匹配以字母 t 开头并以 t 结尾的字符串在下面一行中:

this is tecmint, where you get the best good tutorials, how to's, guides, tecmint. 

当您使用模式 /t*t/ 时,您将获得以下可能性:

this is t
this is tecmint
this is tecmint, where you get t
this is tecmint, where you get the best good t
this is tecmint, where you get the best good tutorials, how t
this is tecmint, where you get the best good tutorials, how tos, guides, t
this is tecmint, where you get the best good tutorials, how tos, guides, tecmint

/t*t/ 通配符中的 (*) 允许 awk 选择最后一个选项:

this is tecmint, where you get the best good tutorials, how to's, guides, tecmint

使用带有 set [ 字符 ] 的 awk

以集合[al1]为例,这里awk将匹配所有包含字符al1的字符串在文件 /etc/hosts 的一行中。

awk '/[al1]/{print}' /etc/hosts

下一个示例匹配以 Kk 开头,后跟 T 的字符串:

awk '/[Kk]T/{print}' /etc/hosts 

指定范围内的字符

用 awk 理解字符:

  1. [0-9] 表示单个数字
  2. [a-z] 表示匹配单个小写字母
  3. [A-Z] 表示匹配单个大写字母
  4. [a-zA-Z] 表示匹配单个字母
  5. [a-zA-Z 0-9] 表示匹配单个字母或数字

让我们看下面的一个例子:

awk '/[0-9]/{print}' /etc/hosts 

在上面的示例中,文件 /etc/hosts 中的所有行至少包含一个数字 [0-9]

将 Awk 与 (^) 元字符结合使用

它匹配以提供的模式开头的所有行,如下例所示:

awk '/^fe/{print}' /etc/hosts
awk '/^ff/{print}' /etc/hosts

将 Awk 与 ($) 元字符结合使用

它匹配以提供的模式结尾的所有行:

awk '/ab$/{print}' /etc/hosts
awk '/ost$/{print}' /etc/hosts
awk '/rs$/{print}' /etc/hosts

将 Awk 与 (\) 转义字符一起使用

它允许您将其后面的字符视为文字,也就是说按原样考虑它。

在下面的示例中,第一个命令打印出文件中的所有行,第二个命令不打印任何内容,因为我想匹配包含 $25.00 的行,但没有使用转义字符。

第三个命令是正确的,因为转义字符已用于按原样读取 $

awk '//{print}' deals.txt
awk '/$25.00/{print}' deals.txt
awk '/\$25.00/{print}' deals.txt

概括

这还不是全部用awk命令行过滤工具,上面的例子介绍了awk的基本操作。在接下来的部分中,我们将进一步介绍如何使用 awk 的复杂功能。感谢您阅读本文,如有任何补充或澄清,请在评论部分发表评论。