跳转到内容

Awk 入门/搜索模式 (1)

来自 Wikibooks,开放世界中的开放书籍

如你所知,Awk 会逐行遍历文件,并对匹配搜索模式的每一行执行代码块。到目前为止,我们只使用了非常简单的搜索模式,例如 /gold/,但你现在将学习更高级的搜索模式。本页上的搜索模式被称为正则表达式。正则表达式是一组规则,可以匹配特定的字符序列。

简单模式

[编辑 | 编辑源代码]

可以指定的 最简单 的搜索模式类型是简单字符串,用正斜杠 (/) 括起来。例如

/The/

这会搜索包含字符串 "The" 的任何行。这不会匹配 "the",因为 Awk 是区分大小写的,但它会匹配像 "There" 或 "Them" 这样的单词。

这是最原始的搜索模式。Awk 定义了特殊字符或元字符,可以用来使搜索更具体。例如,在字符串前面加上 ^ ("插入符号") 会告诉 Awk 在输入行的开头搜索字符串。例如

/^The/

这会匹配任何以字符串 "The" 开头的行。包含 "The" 但不以其开头的行将不会匹配。

类似地,在字符串后面加上 $ 会匹配任何以搜索模式结尾的行。例如

/The$/

在本例中,不以 "The" 结尾的行将不会匹配。

但是,如果我们实际上想在文本中搜索 ^$ 这样的字符呢?很简单,我们只需在字符前面加上反斜杠 (\) 即可。例如

/\$/

这将匹配任何包含 "$" 的行。

有许多不同的元字符可用于自定义搜索模式。

字符集

[编辑 | 编辑源代码]

可以使用方括号 ([]) 指定一组备选字符

/[Tt]he/ 

此示例匹配字符串 "The" 和 "the"。还可以指定字符范围。例如

/[a-z]/

这会匹配 "a" 到 "z" 之间的任何字符,以及

/[a-zA-Z0-9]/

这会匹配任何字母或数字。

还可以通过在范围前面加上 ^ 来排除字符范围。这与匹配字符串开头的插入符号不同,因为它位于方括号内。例如

/^[^a-zA-Z0-9]/

这会匹配任何以字母或数字开头的行。实际上,你可以在字符集中包含插入符号,确保它不是列出的第一个字符。

竖线 (|) 允许将正则表达式进行逻辑 OR 操作。例如

/(^Germany)|(^Netherlands)/

这会匹配以单词 "Germany" 单词 "Netherlands" 开头的行。请注意如何使用括号对这两个表达式进行分组。

通配符

[编辑 | 编辑源代码]

点 (.) 允许 "通配符" 匹配,这意味着它可以用于指定任何任意字符。例如

/f.n/

这将匹配 "fan"、"fun"、"fin",以及 "fxn"、"f4n",以及任何其他以 f 开头,一个字符,然后以 n 结尾的字符串。

这种点通配符的使用对于 UNIX shell 用户来说应该很熟悉,但 Awk 对 * 通配符的解释略有不同。在 UNIX shell 中,* 会替换为任意长度的任意字符字符串,包括零,而在 Awk 中,* 只会匹配前一个字符或表达式的零次或多次重复。例如,"a*" 会匹配 "a"、"aa"、"aaa" 等。这意味着 ".*" 会匹配任何字符字符串。作为一个更复杂的示例,

/(ab|c)*/

这会匹配 "ab"、"abab"、"ababab"、"c"、"cc"、"ccc",甚至 "abc"、"ababc"、"cabcababc",或任何其他类似的组合。

还有其他字符允许匹配重复的字符。? 匹配前一个正则表达式的正好零次或一次出现,而 + 匹配前一个正则表达式的 一次或多次出现。例如

/^[+-]?[0-9]+$/

这会匹配任何只包含(可能带符号的)整数的 行。这是一个有点令人困惑的例子,将其分解成部分是有帮助的

  • ^ 在行的开头查找字符串。
  • [+-]? 指定数字可能的 "+" 或 "-" 符号。
  • [0-9]+ 指定至少一位数字 "0" 到 "9"。
  • $ 指定行以数字结尾。

特定重复

[编辑 | 编辑源代码]

虽然这种语法由 Single Unix Specification 定义,但许多 awk 没有实现此功能。在 GNU Awk 4.0 之前的版本中,你需要—posix 或—re-interval 选项来启用它。

如果要将正则表达式匹配特定次数,可以使用花括号 ({})。例如

/f[eo]{2}t/

这会匹配 "foot" 或 "feet"。

要指定数字为最小值,请在后面加上逗号。

/[0-9]{3,}/

这会匹配至少三位数的数字。这是编写以下代码的更简单的方法

/[0-9][0-9][0-9]+/

可以在花括号中放置两个用逗号分隔的数字来指定一个范围。

/^[0-9]{4,7}$/

这会匹配包含 4 位、5 位、6 位或 7 位数字的行。数字过多或不足,则不会匹配。

除非你已经熟悉正则表达式,否则你应该尝试编写一些自己的正则表达式。为了查看你是否写对了,可以编写一个简单的 Awk 程序来打印任何匹配表达式的行,并测试它。

  1. 编写一个正则表达式来匹配邮政编码。美国邮政编码由 5 位数字和可选的连字符以及另外 4 位数字组成。
  2. 编写一个正则表达式来匹配任何数字,包括可选的小数点后跟更多数字。
  3. 编写一个正则表达式来查找电子邮件地址。查找有效的字符(字母、数字、点和下划线),后跟 "@",然后是更多有效的字符,至少包含一个点。
  4. 编写一个正则表达式来匹配电话号码。它应该处理区号、分机号,以及可选的连字符和括号来对数字进行分组。确保它不会匹配过长或过短的电话号码。

在下一页中,你将学习其他类型的搜索模式。

华夏公益教科书