当您学习一门新的编程语言时,最好专注于大多数编程语言共有的东西
- 变量 – 存储信息的地方
- 表达式 – 计算事物的方法
- 语句 – 程序中表达状态变化的方式
这些概念是大多数编程语言的基础。
一旦你理解了这些概念,你就可以开始弄清楚其余的部分。例如,大多数语言都有其设计所支持的“做事方式”,而这些方式可能因程序而异。这些方式包括模块化(将相关功能组合在一起)、声明式与命令式、面向对象、低级与高级语法特性等等。许多程序员熟悉的一个例子是“仪式感”,即在解决问题之前设置场景所需的工作量。据说 Java 编程语言具有显著的仪式感要求,这源于其设计,它要求所有代码都必须在类中定义。
回到基础知识。编程语言通常具有相似之处。一旦你掌握了一门编程语言,就可以开始学习另一门语言的基础知识,以体会这门新语言的差异。
一个好的方法是创建一组基本的测试程序。有了这些程序,学习就可以从这些相似之处开始。
你可以使用的一个测试程序是“猜数字”程序。计算机选择一个介于 1 到 100 之间的数字,并要求你猜这个数字。程序循环运行,直到你猜对为止。
“猜数字”程序练习了编程语言中的几个概念
- 变量
- 输入
- 输出
- 条件评估
- 循环
这是一个学习新编程语言的绝佳实践实验。
注意:本文改编自 Moshe Zadka 关于在 Julia 中使用这种方法的文章和 Jim Hall 关于在 Bash 中使用这种方法的文章。
用 awk 猜数字
让我们编写一个“猜数字”游戏作为 Awk 程序。
Awk 是动态类型的,是一种面向数据转换的脚本语言,并且对交互式使用具有出乎意料的良好支持。Awk 自 20 世纪 70 年代以来就已存在,最初是 Unix 操作系统的一部分。如果你不了解 Awk 但喜欢电子表格,这是一个信号…… 去学习 Awk!
你可以通过编写一个“猜数字”游戏的版本来开始探索 Awk。
这是我的实现(带有行号,以便我们可以查看一些具体的功能)
1 BEGIN {
2 srand(42)
3 randomNumber = int(rand() * 100) + 1
4 print "random number is",randomNumber
5 printf "guess a number between 1 and 100\n"
6 }
7 {
8 guess = int($0)
9 if (guess < randomNumber) {
10 printf "too low, try again:"
11 } else if (guess > randomNumber) {
12 printf "too high, try again:"
13 } else {
14 printf "that's right\n"
15 exit
16 }
17 }
我们可以立即看到 Awk 控制结构与 C 或 Java 的控制结构之间的相似之处,但与 Python 不同。在诸如 if-then-else 或 while 之类的语句中,then、else 和 while 部分采用语句或用 { 和 } 括起来的语句组。但是,关于 AWk,从一开始就需要理解一个很大的不同之处
从设计上讲,Awk 是围绕数据管道构建的。
那是什么意思?大多数 Awk 程序都是代码片段,它们接收一行输入,对数据进行一些处理,然后将其写入输出。Awk 认识到对这种转换管道的需求,默认情况下提供了所有转换管道。让我们通过上面的程序来探讨这一点,方法是提出一个基本问题:从控制台“读取数据”的结构在哪里?
答案是 – 它是内置的。特别是,第 7 – 17 行告诉 Awk 如何处理读取的每一行。鉴于这种上下文,很容易看出第 1 – 6 行在读取任何数据之前执行。
更具体地说,第 1 行上的 BEGIN 关键字是一种“模式”,在这种情况下,它指示 Awk 在读取任何数据之前,应执行 BEGIN 后面的 { … } 中的内容。类似的 END 关键字(在本程序中未使用)指示 Awk 在读取完所有内容后应执行的操作。
回到第 7 – 17 行,我们看到它们创建了一个代码块 { … },它很相似,但前面没有关键字。由于 { 之前没有任何东西供 Awk 匹配,它会将此行应用于接收到的每一行输入。每行输入都将作为用户的猜测输入。
让我们看看正在执行的代码。首先是前导码,它在读取任何输入之前发生。
在第 2 行中,我们使用数字 42 初始化随机数生成器(如果我们不提供参数,则使用系统时钟)。42? 当然是 42。第 3 行计算一个介于 1 到 100 之间的随机数,第 4 行出于调试目的打印出该数字。第 5 行邀请用户猜一个数字。请注意,此行使用 printf
,而不是 print
。与 C 类似,printf
的第一个参数是用于格式化输出的模板。
现在用户知道程序需要输入,她可以在控制台上键入一个猜测。Awk 将此猜测提供给第 7 – 17 行中的代码,如前所述。第 18 行将输入记录转换为整数;$0
表示整个输入记录,而 $1
表示输入记录的第一个字段,$2
表示第二个字段,依此类推。是的,Awk 将输入行拆分为组成字段,使用预定义的分隔符,该分隔符默认为空格。第 9 – 15 行将猜测与随机数进行比较,打印适当的响应。如果猜测正确,则第 15 行会过早退出输入行处理管道。
简单!
鉴于 Awk 程序的非常规结构,即代码片段对特定的输入行配置做出反应并处理数据,让我们看看另一种结构,只是为了了解过滤部分是如何工作的
1 BEGIN {
2 srand(42)
3 randomNumber = int(rand() * 100) + 1
4 print "random number is",randomNumber
5 printf "guess a number between 1 and 100\n"
6 }
7 int($0) < randomNumber {
8 printf "too low, try again: "
9 }
10 int($0) > randomNumber {
11 printf "too high, try again: "
12 }
13 int($0) == randomNumber {
14 printf "that's right\n"
15 exit
16 }
第 1 – 6 行没有改变。但是现在我们看到第 7 – 9 行是当行的整数值小于随机数时执行的代码,第 10 – 12 行是当行的整数值大于随机数时执行的代码,第 13 – 16 行是当两者匹配时执行的代码。
这应该看起来“酷但奇怪” – 例如,为什么我们要重复计算 int($0)
?当然,这将是一种解决问题的奇怪方式。但是这些模式可能是分离条件处理的非常棒的方法,因为它们可以采用正则表达式或 Awk 支持的任何其他结构。
为了完整性,我们可以使用这些模式将通用计算与仅适用于特定情况的事物分开。这是第三个版本来说明
1 BEGIN {
2 srand(42)
3 randomNumber = int(rand() * 100) + 1
4 print "random number is",randomNumber
5 printf "guess a number between 1 and 100\n"
6 }
7 {
8 guess = int($0)
9 }
10 guess < randomNumber {
11 printf "too low, try again: "
12 }
13 guess > randomNumber {
14 printf "too high, try again: "
15 }
16 guess == randomNumber {
17 printf "that's right\n"
18 exit
19 }
认识到无论输入什么值,都需要将其转换为整数,我们创建了第 7 – 9 行来做到这一点。现在,三组行,10 – 12、13 – 15 和 16 – 19,引用了已经定义的变量 guess,而不是每次都转换输入行。
让我们回到我们想要学习的事物列表
- 变量 – 是的,Awk 有这些;我们可以推断输入数据以字符串形式出现,但在需要时可以转换为数值
- 输入 – Awk 只是通过其“数据转换管道”方法来读取内容
- 输出 – 我们已经使用 Awk 的
print
和printf
过程将内容写入输出 - 条件评估 – 我们已经了解了 Awk 的 if-then-else 和响应特定输入行配置的输入过滤器
- 循环 – 咦,想想看!我们这里不需要循环,再次感谢 Awk 采用的“数据转换管道”方法;循环“自然发生”。请注意,用户可以通过向 Awk 发送文件结束信号来提前退出管道(在使用 Linux 终端窗口时按 CTRL-D)
值得考虑不需要循环来处理输入的重要性。Awk 长期以来保持生命力的一个原因是 Awk 程序很紧凑,它们紧凑的原因之一是不需要样板代码来从控制台或文件读取。
让我们运行程序
$ awk -f guess.awk
random number is 25
guess a number between 1 and 100: 50
too high, try again: 30
too high, try again: 10
too low, try again: 25
that's right
$
我们没有涵盖的一件事是注释。Awk 注释以 #
开头,以行尾结尾。
总结
Awk 功能非常强大,这个“猜数字”游戏是入门的绝佳方式。但这不应该是你旅程的终点。你可以 阅读关于 Awk 和 Gawk(GNU Awk)的历史,Gawk 是 Awk 的扩展版本,如果你运行的是 Linux,它可能就是你计算机上安装的版本,或者 阅读有关其最初开发人员的原始版本的所有信息。
你还可以 下载我们的速查表,以帮助你跟踪你学习的所有内容。
4 条评论