mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-10 22:21:11 +08:00
Update 20191104 Fields, records, and variables in awk.md
This commit is contained in:
parent
8d4a1c7db1
commit
e1a04c2bb7
@ -7,12 +7,12 @@
|
||||
[#]: via: (https://opensource.com/article/19/11/fields-records-variables-awk)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Fields, records, and variables in awk awk中字段,记录和变量
|
||||
awk中的字段,记录和变量
|
||||
======
|
||||
在我们这个系列的第二部分,我们会学习到字段,记录和一些非常有用的awk变量。
|
||||
这个系列的第二篇,我们会学到 字段,记录和一些非常有用的awk变量。
|
||||
![Man at laptop on a mountain][1]
|
||||
|
||||
Awk 有好几个变种: 最早版本的 **awk**, 是1977 年 AT&T Bell 实验室所创造的。还有一些重构版本,例如**mawk**, **nawk**。现在我们能在大多数Linux 发行版中见到的,是 GNU awk,也叫**gawk**。 在大多数 Linux 版本中,awk 和 gawk 都是指向 GNU awk 的链接。 如果输入awk命令,也是一样的效果。 在 [GNU awk 用户手册][2]中能看到 awk 和 gawk 的全部历史。
|
||||
Awk 有好几个变种: 最早的 **awk**, 是1977 年 AT&T Bell 实验室所创。它还有一些重构版本,例如 **mawk**, **nawk**。在大多数Linux 发行版中能见到的,是 GNU awk,也叫**gawk**。 在大多数 Linux 发行版中,awk 和 gawk 都是指向 GNU awk 的链接。 输入awk命令,也是同样的效果。 [GNU awk 用户手册][2]中,能看到 awk 和 gawk 的全部历史。
|
||||
|
||||
这一系列的[第一篇文章][3] 介绍了awk 命令的基本格式:
|
||||
|
||||
@ -20,7 +20,7 @@ Awk 有好几个变种: 最早版本的 **awk**, 是1977 年 AT&T Bell 实
|
||||
`$ awk [options] 'pattern {action}' inputfile`
|
||||
```
|
||||
|
||||
Awk 是一个命令,后面要接选项 (比如用 **-F** 来定义字段分隔符)。 你想让awk 执行的部分需要写在 两个单引号之间,至少在终端中需要这么做。 在awk 命令中,为了进一步强调你想要执行的部分,可以用 **-e** 选项来突出显示 (但这不是必须的):
|
||||
Awk 是一个命令,后面要接选项 (比如用 **-F** 来定义字段分隔符)。 想让awk 执行的部分需要写在 两个单引号之间,至少在终端中需要这么做。 在awk 命令中,为了进一步强调你想要执行的部分,可以用 **-e** 选项来突出显示 (但这不是必须的):
|
||||
|
||||
|
||||
```
|
||||
@ -31,12 +31,11 @@ green
|
||||
[...]
|
||||
```
|
||||
|
||||
### Records and fields 记录和字段
|
||||
### 记录和字段
|
||||
|
||||
Awk views its input data as a series of _records_, which are usually newline-delimited lines. In other words, awk generally sees each line in a text file as a new record. Each record contains a series of _fields_. A field is a component of a record delimited by a _field separator_.
|
||||
Awk 将输入数据视为 一系列 _记录_ , 通常来说是按行分割的。 换句话说,awk 通常将文本中的每一行视作一个记录。每一记录包含多个 _字段_. 一个字段是由 _字段分隔符_ 分隔出的,记录的一部分.
|
||||
Awk 将输入数据视为 一系列 _记录_ , 通常是按行分割的。 换句话说,awk 将文本中的每一行视作一个记录。每一记录包含多个 _字段_. 一个字段由 _字段分隔符_ 分隔开来,字段是记录的一部分.
|
||||
|
||||
默认情况下,awk 将各种空白符,如空格,tab,换行符,视为分隔符。 值得注意的是,awk 将多个 _空格_ 视为一个分隔符。所以下面这行文本有两个字段:
|
||||
默认情况下,awk 将各种空白符,如空格,tab,换行符等视为分隔符。 值得注意的是,在awk 中,多个 _空格_ 将被视为一个分隔符。所以下面这行文本有两个字段:
|
||||
|
||||
|
||||
```
|
||||
@ -50,7 +49,7 @@ Awk 将输入数据视为 一系列 _记录_ , 通常来说是按行分割的
|
||||
`tuxedo black`
|
||||
```
|
||||
|
||||
其他分隔符,在程序中不是这么处理的。假设字段分隔符是逗号,如下所示的记录就分为三个字段。其中一个字段可能会只有0个字节长(假设这一字段中不包含隐藏字符)
|
||||
其他分隔符,在程序中不是这么处理的。假设字段分隔符是逗号,如下所示的记录,就有三个字段。其中一个字段可能会是0个字节(假设这一字段中不包含隐藏字符)
|
||||
|
||||
```
|
||||
`a,,b`
|
||||
@ -58,13 +57,13 @@ Awk 将输入数据视为 一系列 _记录_ , 通常来说是按行分割的
|
||||
|
||||
### awk 程序
|
||||
|
||||
awk 命令的 _程序部分_ 是由一系列规则组成的。通常来说,在程序中每个规则占一行(尽管这不是必须的)。 每个规则由一个模式,或者一个/多个动作组成:
|
||||
awk 命令的 _程序部分_ 是由一系列规则组成的。通常来说,程序中每个规则占一行(尽管这不是必须的)。 每个规则由一个模式,或一个/多个动作组成:
|
||||
|
||||
```
|
||||
`pattern { action }`
|
||||
```
|
||||
|
||||
在一个规则中,你可以通过定义模式,来确定行动是否会在记录中执行。 模式可以是简单的比较条件,正则表达式,两者的结合或者更多。
|
||||
在一个规则中,你可以通过定义模式,来确定行动是否会在记录中执行。 模式可以是简单的比较条件,正则表达式,甚至两者结合等等。
|
||||
|
||||
这个例子中,程序 _只会_ 显示包含 单词 “raspberry” 的记录:
|
||||
|
||||
@ -76,13 +75,13 @@ raspberry red 99
|
||||
|
||||
如果没有文本符合模式,最终结果会对应所有记录。
|
||||
|
||||
并且,在一条规则只包含一个模式时,相当于在整个记录上执行 **{ print }** 命令。
|
||||
并且,在一条规则只包含一个模式时,相当于对整个记录执行 **{ print }** 。
|
||||
|
||||
Awk 程序本质上是 _数据驱动_ 的,命令执行结果取决于数据。所以,与其他编程语言中的程序相比,它还是有些区别的。
|
||||
|
||||
### NF 变量
|
||||
|
||||
每个字段都有指定变量,但针对字段和记录,也有一些特殊的变量。 **NF** 变量能存储awk在当前记录中找到的数字字段。可在屏幕上显示出变量内容,或将其用于测试。 下面例子中的数据,来自前一篇文章中的 [文本][3]:
|
||||
每个字段都有指定变量,但针对字段和记录,也存在一些特殊变量。 **NF** 变量,能存储awk在当前记录中找到的数字字段。其内容可在屏幕上显示,也可用于测试。 下面例子中的数据,来自上篇文章[文本][3]:
|
||||
|
||||
|
||||
```
|
||||
@ -93,7 +92,7 @@ banana yellow 6 (3)
|
||||
[...]
|
||||
```
|
||||
|
||||
Awk 的 **print** 函数会接受一系列参数(可以是变量或者字符),并将它们拼接起来。这就是为什么在这一例子中,在每行结尾处,awk 会显示一个被括号括起来的整数。
|
||||
Awk 的 **print** 函数会接受一系列参数(可以是变量或者字符),并将它们拼接起来。这就是为什么在这个例子里,每行结尾处,awk 会显示一个被括号括起来的整数。
|
||||
|
||||
### NR 变量
|
||||
|
||||
@ -109,7 +108,7 @@ $ awk '{ print NR ": " $0 }' colours.txt
|
||||
[...]
|
||||
```
|
||||
|
||||
注意,在这个命令后输入数据时,可以不同于在 **print** 后,参数间可以不写空格,尽管这样会降低可读性:
|
||||
注意,在这个命令下输入数据时,可以不遵循在 **print** 后的规则,参数间可以不写空格,尽管这样会降低可读性:
|
||||
|
||||
|
||||
```
|
||||
@ -118,14 +117,14 @@ $ awk '{ print NR ": " $0 }' colours.txt
|
||||
|
||||
### printf() 函数
|
||||
|
||||
为了输出结果时格式更灵活,你可以使用 awk 的 **printf()** 函数。 它与C,Lua,Bash和其他语言中的 **printf** 相类似。 它也接受 _格式_ ,后用逗号分隔的参数。参数列表需要写在括号内。
|
||||
为了输出结果时格式更灵活,你可以使用 awk 的 **printf()** 函数。 它与C,Lua,Bash和其他语言中的 **printf** 相类似。 它也接受 _格式_ ,加逗号分隔的参数。参数列表需要写在括号里。
|
||||
|
||||
|
||||
```
|
||||
`$ printf format, item1, item2, ...`
|
||||
```
|
||||
|
||||
格式这一参数(也叫 _格式符_ ) 定义了其他参数会如何显示。 这一功能是用 _格式修饰符_ 来实现的。 用 **%s** 显示字符, **%d** 显示数字。 下面的**printf** 语句,会在括号内显示字段数量:
|
||||
格式这一参数(也叫 _格式符_ ) 定义了其他参数如何显示。 这一功能是用 _格式修饰符_ 来实现的。 **%s** 显示字符, **%d** 显示数字。 下面的**printf** 语句,会在括号内显示字段数量:
|
||||
|
||||
```
|
||||
$ awk 'printf "%s (%d)\n",$0,NF}' colours.txt
|
||||
@ -136,13 +135,13 @@ banana yellow 6 (3)
|
||||
```
|
||||
|
||||
|
||||
在这个例子里, **%s (%d)** 提供了每一行的输出格式,**$0,NF** 定义了插入 **%s** 和 **%d** 位置的数据。注意,不像**print** 函数,在没有明确指令时下,输出不会转到下一行。 转义字符 **\n** 才会换行。
|
||||
在这个例子里, **%s (%d)** 确定了每一行的输出格式,**$0,NF** 定义了插入 **%s** 和 **%d** 位置的数据。注意,和**print** 函数不同,在没有明确指令时,输出不会转到下一行。出现 转义字符 **\n** 时才会换行。
|
||||
|
||||
### Awk 脚本编程
|
||||
|
||||
这篇文章中出现的所有awk代码,都在Bash终端中执行过。 在更复杂的程序中,将你的命令放在文件( _脚本_ )中,这样会更容易。 **-f FILE** 选项(不要和 **-F** 弄混了,那个选项用于字段分隔符),可用于调用包含可执行程序的文件。
|
||||
这篇文章中出现的所有awk代码,都在Bash终端中执行过。 面对更复杂的程序,将命令放在文件( _脚本_ )中会更容易。 **-f FILE** 选项(不要和 **-F** 弄混了,那个选项用于字段分隔符),可用于指明包含可执行程序的文件。
|
||||
|
||||
例如,这里有一个简单的awk 脚本。 创建一个名为 **example1.awk** 的文件,包含以下内容:
|
||||
举个例子,下面是一个简单的awk 脚本。 创建一个名为 **example1.awk** 的文件,包含以下内容:
|
||||
|
||||
|
||||
```
|
||||
@ -150,10 +149,9 @@ banana yellow 6 (3)
|
||||
/^b/ {print "B: " $0}
|
||||
```
|
||||
|
||||
It's conventional to give such files the extension **.awk** to make it clear that they hold an awk program. This naming is not mandatory, but it gives file managers and editors (and you) a useful clue about what the file is.
|
||||
如果一个文件包含 awk 程序,最好给这些文件 **.awk** 的扩展名。
|
||||
如果一个文件包含 awk 程序,那么在给文件命名时,最好写上 **.awk** 的扩展名。 这样命名不是强制的,但这么做,会给文件管理器,编辑者(和你)一个关于文件内容的,很有用的提示。
|
||||
|
||||
Run the script:
|
||||
执行这一脚本:
|
||||
|
||||
|
||||
```
|
||||
@ -163,12 +161,12 @@ B: banana yellow 6
|
||||
A: apple green 8
|
||||
```
|
||||
|
||||
一个包含 awk 命令的文件,在最开头一行加上 **#!** ,就可以变成可执行脚本。 创建一个名为 **example2.awk** 的文件,包含以下内容:
|
||||
一个包含 awk 命令的文件,在最开头一行加上 **#!** ,就能变成可执行脚本。 创建一个名为 **example2.awk** 的文件,包含以下内容:
|
||||
|
||||
```
|
||||
#!/usr/bin/awk -f
|
||||
#
|
||||
# Print all but line 1 with the line number on the front
|
||||
# 除了第一行,在其他行前显示行号
|
||||
#
|
||||
|
||||
NR > 1 {
|
||||
@ -177,15 +175,16 @@ NR > 1 {
|
||||
```
|
||||
|
||||
Arguably, there's no advantage to having just one line in a script, but sometimes it's easier to execute a script than to remember and type even a single line. A script file also provides a good opportunity to document what a command does. Lines starting with the **#** symbol are comments, which awk ignores.
|
||||
可以说,脚本中只有一行,大多数情况下没什么用。 但在某些情况下,执行一个脚本,比记住,然后打一条命令要容易的多。 一个脚本文件,也提供了一个记录命令具体作用的好机会。 以 **#** 号开头的行是注释,awk 会忽略它们。
|
||||
|
||||
Grant the file executable permission:
|
||||
给文件可执行权限:
|
||||
|
||||
|
||||
```
|
||||
`$ chmod u+x example2.awk`
|
||||
```
|
||||
|
||||
Run the script:
|
||||
执行脚本:
|
||||
|
||||
|
||||
```
|
||||
@ -197,21 +196,25 @@ $ ./example2.awk colours.txt
|
||||
[...]
|
||||
```
|
||||
|
||||
An advantage of placing your awk instructions in a script file is that it's easier to format and edit. While you can write awk on a single line in your terminal, it can get overwhelming when it spans several lines.
|
||||
|
||||
### Try it
|
||||
将awk 命令放在脚本文件中,有一个好处就是,修改和格式化输出会更容易。在终端中,如果能用一行执行多条awk命令,那么输入多行,才能达到同样效果,就显得有些多余了。
|
||||
|
||||
### 试一试
|
||||
|
||||
You now know enough about how awk processes your instructions to be able to write a complex awk program. Try writing an awk script with more than one rule and at least one conditional pattern. If you want to try more functions than just **print** and **printf**, refer to [the gawk manual][4] online.
|
||||
|
||||
Here's an idea to get you started:
|
||||
你现在已经足够了解, awk 是如何执行指令的了。现在你应该能编写复杂的awk 程序了。 试着编写一个awk 脚本,它需要: 至少包括一个条件模式,以及多个规则。如果你想使用除 **print** 和 **printf** 以外的函数,可以参考在线[ gawk 手册][4] .
|
||||
|
||||
|
||||
下面这个例子是个很好的切入点:
|
||||
|
||||
|
||||
```
|
||||
#!/usr/bin/awk -f
|
||||
#
|
||||
# Print each record EXCEPT
|
||||
# IF the first record contains "raspberry",
|
||||
# THEN replace "red" with "pi"
|
||||
# 显示所有记录 除了出现以下情况
|
||||
# 如果第一个记录 包含 “raspberry”
|
||||
# 将 “red” 替换成 “pi”
|
||||
|
||||
$1 == "raspberry" {
|
||||
gsub(/red/,"pi")
|
||||
@ -220,13 +223,14 @@ $1 == "raspberry" {
|
||||
{ print }
|
||||
```
|
||||
|
||||
Try this script to see what it does, and then try to write your own.
|
||||
试着执行这个脚本,看看输出是什么。接下来就看你自己的了。
|
||||
|
||||
The next article in this series will introduce more functions for even more complex (and useful!) scripts.
|
||||
|
||||
这一系列的下一篇文章,将会介绍更多,能在更复杂(更有用!) 脚本中使用的函数。
|
||||
|
||||
* * *
|
||||
|
||||
_This article is adapted from an episode of [Hacker Public Radio][5], a community technology podcast._
|
||||
_这篇文章改编自 [Hacker Public Radio][5] 系列,一个技术社区博客_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user