mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-25 00:50:15 +08:00
translating finished
This commit is contained in:
parent
49c315e518
commit
df0487ed63
@ -1,208 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (FYJNEVERFOLLOWS )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn awk by coding a "guess the number" game)
|
||||
[#]: via: (https://opensource.com/article/21/1/learn-awk)
|
||||
[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
|
||||
|
||||
Learn awk by coding a "guess the number" game
|
||||
======
|
||||
Programming languages tend to share many common traits. One great way to
|
||||
learn a new language is to create a familiar program. In this article, I
|
||||
will create a "guess the number" game by using awk to demonstrate
|
||||
familiar concepts.
|
||||
![question mark in chalk][1]
|
||||
|
||||
When you learn a new programming language, it's good to focus on the things most programming languages have in common:
|
||||
|
||||
* Variables – places where information is stored
|
||||
* Expressions – ways to calculate things
|
||||
* Statements – the means by which state changes are expressed in a program
|
||||
|
||||
|
||||
|
||||
These concepts are the basis of most programming languages.
|
||||
|
||||
Once you understand these concepts, you can start figuring the rest out. For example, most languages have a "way of doing things" supported by their design, and those ways can be quite different from one program to another. These ways include modularity (grouping related functionality together), declarative vs. imperative, object-orientation, low- vs. high-level syntactic features, and so on. An example familiar to many programmers is "ceremony," that is, the amount of work required to set the scene before tackling the problem. The Java programming language is said to have a significant ceremony requirement, stemming from its design, which requires all code to be defined within a class.
|
||||
|
||||
But back to the basics. Programming languages usually share similarities. Once you know one programming language, start by learning the basics of another to appreciate the differences in that new language.
|
||||
|
||||
A good way to proceed is to create a set of basic test programs. With these in hand, learning starts with these similarities.
|
||||
|
||||
One test program you can use is a "guess the number" program. The computer picks a number between one and one hundred and asks you to guess the number. The program loops until you make a correct guess.
|
||||
|
||||
The "guess the number" program exercises several concepts in programming languages:
|
||||
|
||||
* Variables
|
||||
* Input
|
||||
* Output
|
||||
* Conditional evaluation
|
||||
* Loops
|
||||
|
||||
|
||||
|
||||
That's a great practical experiment to learn a new programming language.
|
||||
|
||||
**Note**: This article is adapted from Moshe Zadka's article on doing using this approach in [Julia][2] and Jim Hall's article on doing it in [Bash][3].
|
||||
|
||||
### Guess the number in awk
|
||||
|
||||
Let's write a "guess the number" game as an Awk program.
|
||||
|
||||
Awk is dynamically typed, is a scripting language oriented toward data transformation, and has surprisingly good support for interactive use. Awk has been around since the 1970s, originally as a part of the Unix operating system. If you don't know Awk but love spreadsheets, this is a sign… [go learn Awk][4]!
|
||||
|
||||
You can begin your exploration of Awk by writing a version of the "guess the number" game.
|
||||
|
||||
Here is my implementation (with line numbers so we can review some of the specific features):
|
||||
|
||||
|
||||
```
|
||||
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 }
|
||||
```
|
||||
|
||||
We can immediately see similarities between Awk control structures and those of C or Java, but unlike Python. In statements such as _if-then-else_ or _while_, the _then_, _else_, and _while_ parts take either a statement or a group of statements enclosed within **{** and **}**. However, there is one big difference about AWk that needs to be understood from the start:
|
||||
|
||||
By design, Awk is built around a data pipeline.
|
||||
|
||||
What does that mean? Most Awk programs are snippets of code that receive a line of input, do something with the data, and write it to output. Recognizing the need for such a transformation pipeline, Awk by default provides all the transformation plumbing. Let's explore that through the above program by asking a basic question: Where is the 'read data from the console' structure?
|
||||
|
||||
The answer to that is – it's built-in. In particular, lines 7 – 17 tell Awk what to do with each line that is read. Given that context, it's pretty easy to see that lines 1 – 6 are executed before anything is read.
|
||||
|
||||
More specifically, the **BEGIN** keyword on line 1 is a kind of "pattern," in this case indicating to Awk that, before reading any data, it should execute what follows the **BEGIN** in the { … }. A similar **END** keyword, not used in this program, indicates to Awk what to do when everything has been read.
|
||||
|
||||
Coming back to lines 7 – 17, we see they create a block of code { … } that is similar, but there is no keyword in front. Because there is nothing before the **{** for Awk to match, it will apply this line to every line of input received. Each line of input will be entered as guesses by the user.
|
||||
|
||||
Let's look at the code being executed. First, the preamble that happens before any input is read.
|
||||
|
||||
In line 2, we initialize the random number generator with the number 42 (if we don't provide an argument, the system clock is used). 42? [Of course 42][5]. Line 3 calculates a random number between 1 and 100, and line 4 prints that number out for debugging purposes. Line 5 invites the user to guess a number. Note this line uses `printf`, not `print`. Like C, `printf'`s first argument is a template used to format the output.
|
||||
|
||||
Now that the user is aware the program expects input, she can type a guess on the console. Awk supplies this guess to the code in lines 7 – 17, as mentioned previously. Line 18 converts the input record to an integer; `$0` indicates the entire input record, whereas `$1` indicates the first field of the input record, `$2` the second, and so on. Yup, Awk splits an input line into constituent fields, using the predefined separator, which defaults to white space. Lines 9 – 15 compare the guess to the random number, printing appropriate responses. If the guess is correct, line 15 exits prematurely from the input line processing pipeline.
|
||||
|
||||
Simple!
|
||||
|
||||
Given the unusual structure of Awk programs as code snippets that react to specific input line configurations and do stuff with the data, let’s look at an alternative structure just to see how the filtering part works:
|
||||
|
||||
|
||||
```
|
||||
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 }
|
||||
```
|
||||
|
||||
Lines 1 – 6 haven’t changed. But now we see that lines 7 – 9 is code that is executed when the integer value of the line is less than the random number, lines 10 – 12 is code that is executed when the integer value of the line is greater than the random number, and lines 13 – 16 is code that is executed when the two match.
|
||||
|
||||
This should seem "cool but weird" – why would we repeatedly calculate `int($0)`, for example? And for sure, it would be a weird way to solve the problem. But those patterns can be really quite wonderful ways to separate conditional processing since they can employ regular expressions or any other structure supported by Awk.
|
||||
|
||||
For completeness, we can use these patterns to separate common computations from things that only apply to specific circumstances. Here’s a third version to illustrate:
|
||||
|
||||
|
||||
```
|
||||
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 }
|
||||
```
|
||||
|
||||
Recognizing that, no matter what value of input comes in, it needs to be converted to an integer, we have created lines 7 – 9 to do just that. Now the three groups of lines, 10 – 12, 13 – 15 and 16 – 19, refer to the already-defined variable guess instead of converting the input line each time.
|
||||
|
||||
Let's go back to the list of things we wanted to learn:
|
||||
|
||||
* variables – yup, Awk has those; we can infer that input data comes in as strings but can be converted to a numeric value when required
|
||||
* input – Awk just sends input through its "data transformation pipeline" approach to reading stuff
|
||||
* output – we have used Awk's `print` and `printf` procedures to write stuff to output
|
||||
* conditional evaluation – we have learned about Awk's _if-then-else_ and input filters that respond to specific input line configurations
|
||||
* loops – huh, imagine that! We didn't need a loop here, once again, thanks to the "data transformation pipeline" approach that Awk takes; the loop "just happens." Note the user can exit the pipeline prematurely by sending an end-of-file signal to Awk (a **CTRL-D** when using a Linux terminal window)
|
||||
|
||||
|
||||
|
||||
It's well worth considering the importance of not needing a loop to handle input. One reason Awk has remained viable for so long is that Awk programs are compact, and one of the reasons they are compact is there is no boilerplate required to read from the console or a file.
|
||||
|
||||
Let's run the program:
|
||||
|
||||
|
||||
```
|
||||
$ 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
|
||||
$
|
||||
```
|
||||
|
||||
One thing we didn't cover was comments. An Awk comment begins with a `#` and ends with the end of line.
|
||||
|
||||
### Wrap up
|
||||
|
||||
Awk is incredibly powerful and this "guess the number" game is a great way to get started. It shouldn't be the end of your journey, though. You can [read about the history of Awk and Gawk (GNU Awk)][6], an expanded version of Awk and probably the one you have on your computer if you're running Linux, or [read all about the original from its initial developers][7].
|
||||
|
||||
You can also [download our cheatsheet][8] to help you keep track of everything you learn.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/learn-awk
|
||||
|
||||
作者:[Chris Hermansen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/FYJNEVERFOLLOWS)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/clhermansen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/question-mark_chalkboard.jpg?itok=DaG4tje9 (question mark in chalk)
|
||||
[2]: https://opensource.com/article/20/12/julia
|
||||
[3]: https://opensource.com/article/20/12/learn-bash
|
||||
[4]: https://opensource.com/article/20/9/awk-ebook
|
||||
[5]: https://en.wikipedia.org/wiki/42_(number)#The_Hitchhiker's_Guide_to_the_Galaxy
|
||||
[6]: https://www.gnu.org/software/gawk/manual/html_node/History.html
|
||||
[7]: https://archive.org/details/pdfy-MgN0H1joIoDVoIC7
|
||||
[8]: https://opensource.com/downloads/cheat-sheet-awk-features
|
@ -0,0 +1,199 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (FYJNEVERFOLLOWS )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn awk by coding a "guess the number" game)
|
||||
[#]: via: (https://opensource.com/article/21/1/learn-awk)
|
||||
[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
|
||||
|
||||
编写一个“猜数”游戏的程序来学习 awk
|
||||
======
|
||||
编程语言往往具有许多共同特征。学习一门新语言的好方法是去写一个熟悉的程序。在本文中,我将会使用 awk 编写一个“猜数”程序来展示熟悉的概念。
|
||||
|
||||
![question mark in chalk][1]
|
||||
|
||||
当你学习一门新的编程语言时,最好把重点放在大多数编程语言都有的共同点上:
|
||||
* 变量 —— 存储信息的地方
|
||||
* 表达式 —— 计算的方法
|
||||
* 语句 —— 在程序中表示状态变化的方法
|
||||
|
||||
|
||||
这些概念是大多是编程语言的基础。
|
||||
|
||||
一旦你理解了这些概念,你就可以开始把其他的弄清楚。例如,大多数语言都有得到其设计支持的“处理方式”,这些方式在不同语言之间可能有很大的不同。这些方法包括模块化(将相关功能分组在一起)、声明性与命令性、面向对象、低级与高级语法特性等等。许多程序员熟悉的一个例子是“仪式”,即,在处理问题之前设置场景所需的工作量。据说 Java 编程语言有一个重要的仪式要求,这源于它的设计,要求所有代码都在一个类中定义。
|
||||
|
||||
但是回到最基本的,编程语言通常有相似之处。一旦你掌握了一种编程语言,就从学习另一种语言的基本知识开始,去品味这种新语言的不同之处。
|
||||
|
||||
继续进行的一个好方法是创建一组基本的测试程序。有了这些,就可以从这些相似之处开始学习。
|
||||
|
||||
你可以选择创建的一个测试程序是“猜数字”程序。电脑从 1 到 100 之间选择一个数字,让你猜这个数字。程序一直循环,直到你猜对为止。
|
||||
|
||||
“猜数字”程序练习了编程语言中的几个概念:
|
||||
* 变量
|
||||
* 输入
|
||||
* 输出
|
||||
* 条件判断
|
||||
* 循环
|
||||
|
||||
|
||||
这是学习一门新的编程语言的一个很好的实践实验。
|
||||
|
||||
|
||||
**注**:本文改编自 Moshe Zadka 关于在 [Julia][2] 中使用这种方法的文章和Jim Hall关于在 [Bash][3] 中使用这种方法的文章。
|
||||
|
||||
### 在 awk 程序中猜数
|
||||
让我们编写一个实现“猜数字”游戏的 awk 程序。
|
||||
|
||||
Awk 是动态类型的,是一种面向数据转换的脚本语言,并且对交互使用有着令人惊讶的良好支持。Awk 出现于 20 世纪 70 年代,最初是 Unix 操作系统的一部分。如果你不了解 Awk,但是喜欢电子表格,可以看一下这个链接 [去学习 Awk][4]!
|
||||
|
||||
您可以通过编写一个版本的“猜数字”游戏来开始对 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!][5] 第 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 的终点。你可以 [阅读关于 Awk 和 Gawk (GNU Awk) 的历史][6],Gawk是 Awk 的扩展版本,如果你在电脑上运行Linux,可能会有这个。或者,你可以 [阅读所有关于它最初开发者的原始版本][7]。
|
||||
|
||||
你还可以 [下载我们的备忘单][8] 来帮你记录下你所学的一切。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/learn-awk
|
||||
|
||||
作者:[Chris Hermansen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[FYJNEVERFOLLOWS](https://github.com/FYJNEVERFOLLOWS)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/clhermansen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/question-mark_chalkboard.jpg?itok=DaG4tje9 (question mark in chalk)
|
||||
[2]: https://opensource.com/article/20/12/julia
|
||||
[3]: https://opensource.com/article/20/12/learn-bash
|
||||
[4]: https://opensource.com/article/20/9/awk-ebook
|
||||
[5]: https://en.wikipedia.org/wiki/42_(number)#The_Hitchhiker's_Guide_to_the_Galaxy
|
||||
[6]: https://www.gnu.org/software/gawk/manual/html_node/History.html
|
||||
[7]: https://archive.org/details/pdfy-MgN0H1joIoDVoIC7
|
||||
[8]: https://opensource.com/downloads/cheat-sheet-awk-features
|
Loading…
Reference in New Issue
Block a user