自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

通過編寫“猜數(shù)字”游戲來學(xué)習(xí) Awk

開發(fā) 后端
編程語言往往具有許多共同特征。學(xué)習(xí)一門新語言的好方法是去寫一個(gè)熟悉的程序。在本文中,我將會(huì)使用 Awk 編寫一個(gè)“猜數(shù)字”程序來展示熟悉的概念。

當(dāng)你學(xué)習(xí)一門新的編程語言時(shí),最好把重點(diǎn)放在大多數(shù)編程語言都有的共同點(diǎn)上:

  • 變量 —— 存儲(chǔ)信息的地方
  • 表達(dá)式 —— 計(jì)算的方法
  • 語句 —— 在程序中表示狀態(tài)變化的方法

這些概念是大多是編程語言的基礎(chǔ)。

一旦你理解了這些概念,你就可以開始把其他的弄清楚。例如,大多數(shù)語言都有由其設(shè)計(jì)所支持的“處理方式”,這些方式在不同語言之間可能有很大的不同。這些方法包括模塊化(將相關(guān)功能分組在一起)、聲明式與命令式、面向?qū)ο蟆⒌图?jí)與高級(jí)語法特性等等。許多程序員比較熟悉的是編程“儀式”,即,在處理問題之前設(shè)置場景所需花費(fèi)的工作。據(jù)說
Java 編程語言有一個(gè)源于其設(shè)計(jì)的重要儀式要求,就是所有代碼都在一個(gè)類中定義。

但從根本上講,編程語言通常有相似之處。一旦你掌握了一種編程語言,就可以從學(xué)習(xí)另一種語言的基本知識(shí)開始,品味這種新語言的不同之處。

一個(gè)好方法是創(chuàng)建一組基本的測試程序。有了這些,就可以從這些相似之處開始學(xué)習(xí)。

你可以選擇創(chuàng)建的一個(gè)測試程序是“猜數(shù)字”程序。電腦從 1 到 100 之間選擇一個(gè)數(shù)字,讓你猜這個(gè)數(shù)字。程序一直循環(huán),直到你猜對(duì)為止。

“猜數(shù)字”程序練習(xí)了編程語言中的幾個(gè)概念:

  • 變量
  • 輸入
  • 輸出
  • 條件判斷
  • 循環(huán)

這是學(xué)習(xí)一門新的編程語言的一個(gè)很好的實(shí)踐實(shí)驗(yàn)。

:本文改編自 Moshe Zadka 在 Julia 中使用這種方法和 Jim Hall在 Bash 中使用這種方法的文章。

在 awk 程序中猜數(shù)

讓我們編寫一個(gè)實(shí)現(xiàn)“猜數(shù)字”游戲的 Awk 程序。

Awk 是動(dòng)態(tài)類型的,這是一種面向數(shù)據(jù)轉(zhuǎn)換的腳本語言,并且對(duì)交互使用有著令人驚訝的良好支持。Awk 出現(xiàn)于 20 世紀(jì) 70 年代,最初是 Unix 操作系統(tǒng)的一部分。如果你不了解 Awk,但是喜歡電子表格,這就是一個(gè)你可以 去學(xué)習(xí) Awk 的信號(hào)!

您可以通過編寫一個(gè)“猜數(shù)字”游戲版本來開始對(duì) Awk 的探索。

以下是我的實(shí)現(xiàn)(帶有行號(hào),以便我們可以查看一些特定功能):

BEGIN {
srand(42)
randomNumber = int(rand() * 100) + 1
print "random number is",randomNumber
printf "guess a number between 1 and 100\n"
}
{
guess = int($0)
if (guess < randomNumber) {
printf "too low, try again:"
} else if (guess > randomNumber) {
printf "too high, try again:"
} else {
printf "that's right\n"
exit
}
}

我們可以立即看到 Awk 控制結(jié)構(gòu)與 C 或 Java 的相似之處,但與 Python 不同。 在像 ??if-then-else??、??while?? 這樣的語句中,??then??、??else?? 和 ??while?? 部分接受一個(gè)語句或一組被 ??{?? 和 ??}?? 包圍的語句。然而,Awk 有一個(gè)很大的區(qū)別需要從一開始就了解:

根據(jù)設(shè)計(jì),Awk 是圍繞數(shù)據(jù)管道構(gòu)建的。

這是什么意思呢?大多數(shù) Awk 程序都是一些代碼片段,它們接收一行輸入,對(duì)數(shù)據(jù)做一些處理,然后將其寫入輸出。認(rèn)識(shí)到這種轉(zhuǎn)換管道的需要,Awk 默認(rèn)情況下提供了所有的轉(zhuǎn)換管道。讓我們通過關(guān)于上面程序的一個(gè)基本問題來探索:“從控制臺(tái)讀取數(shù)據(jù)”的結(jié)構(gòu)在哪里?

答案是——“內(nèi)置的”。特別的,第 7-17 行告訴 Awk 如何處理被讀取的每一行。在這種情況下,很容易看到第 1-6 行是在讀取任何內(nèi)容之前被執(zhí)行的。

更具體地說,第 1 行上的 ??BEGIN?? 關(guān)鍵字是一種“模式”,在本例中,它指示 Awk 在讀取任何數(shù)據(jù)之前,應(yīng)該先執(zhí)行 ??{ ... }?? 中 ??BEGIN?? 后面的內(nèi)容。另一個(gè)類似的關(guān)鍵字 ??END??,在這個(gè)程序中沒有被使用,它指示 Awk 在讀取完所有內(nèi)容后要做什么。

回到第 7-17 行,我們看到它們創(chuàng)建了一個(gè)類似代碼塊 ??{ ... }?? 的片段,但前面沒有關(guān)鍵字。因?yàn)樵?nbsp;??{?? 之前沒有任何東西可以讓 Awk 匹配,所以它將把這一行用于接收每一行輸入。每一行的輸入都將由用戶輸入作為猜測。

讓我們看看正在執(zhí)行的代碼。首先,是在讀取任何輸入之前發(fā)生的序言部分。

在第 2 行,我們用數(shù)字 42 初始化隨機(jī)數(shù)生成器(如果不提供參數(shù),則使用系統(tǒng)時(shí)鐘)。為什么要用 42?當(dāng)然要選 42! 第 3 行計(jì)算 1 到 100 之間的隨機(jī)數(shù),第 4 行輸出該隨機(jī)數(shù)以供調(diào)試使用。第 5 行邀請(qǐng)用戶猜一個(gè)數(shù)字。注意這一行使用的是 ??printf??,而不是 ??print??。和 C 語言一樣,??printf?? 的第一個(gè)參數(shù)是一個(gè)用于格式化輸出的模板。

既然用戶知道程序需要輸入,她就可以在控制臺(tái)上鍵入猜測。如前所述,Awk 將這種猜測提供給第 7-17 行的代碼。第 18 行將輸入記錄轉(zhuǎn)換為整數(shù);??$0?? 表示整個(gè)輸入記錄,而 ??$1?? 表示輸入記錄的第一個(gè)字段,??$2?? 表示第二個(gè)字段,以此類推。是的,Awk 使用預(yù)定義的分隔符(默認(rèn)為空格)將輸入行分割為組成字段。第 9-15 行將猜測結(jié)果與隨機(jī)數(shù)進(jìn)行比較,打印適當(dāng)?shù)捻憫?yīng)。如果猜對(duì)了,第 15 行就會(huì)從輸入行處理管道中提前退出。

就這么簡單!

考慮到 Awk 程序不同尋常的結(jié)構(gòu),代碼片段會(huì)對(duì)特定的輸入行配置做出反應(yīng),并處理數(shù)據(jù),讓我們看看另一種結(jié)構(gòu),看看過濾部分是如何工作的:

BEGIN {
srand(42)
randomNumber = int(rand() * 100) + 1
print "random number is",randomNumber
printf "guess a number between 1 and 100\n"
}
int($0) < randomNumber {
printf "too low, try again: "
}
int($0) > randomNumber {
printf "too high, try again: "
}
int($0) == randomNumber {
printf "that's right\n"
exit
}

第 1–6 行代碼沒有改變。但是現(xiàn)在我們看到第 7-9 行是當(dāng)輸入整數(shù)值小于隨機(jī)數(shù)時(shí)執(zhí)行的代碼,第 10-12 行是當(dāng)輸入整數(shù)值大于隨機(jī)數(shù)時(shí)執(zhí)行的代碼,第 13-16 行是兩者相等時(shí)執(zhí)行的代碼。

這看起來“很酷但很奇怪” —— 例如,為什么我們會(huì)重復(fù)計(jì)算 ??int($0)???可以肯定的是,用這種方法來解決問題會(huì)很奇怪。但這些模式確實(shí)是分離條件處理的非常好的方式,因?yàn)樗鼈兛梢允褂谜齽t表達(dá)式或 Awk 支持的任何其他結(jié)構(gòu)。

為了完整起見,我們可以使用這些模式將普通的計(jì)算與只適用于特定環(huán)境的計(jì)算分離開來。下面是第三個(gè)版本:

認(rèn)識(shí)到這一點(diǎn),無論輸入的是什么值,都需要將其轉(zhuǎn)換為整數(shù),因此我們創(chuàng)建了第 7-9 行來完成這一任務(wù)?,F(xiàn)在第 10-12、13-15 和 16-19 行這三組代碼,都是指已經(jīng)定義好的變量 guess,而不是每次都對(duì)輸入行進(jìn)行轉(zhuǎn)換。

讓我們回到我們想要學(xué)習(xí)的東西列表:

  • 變量 —— 是的,Awk 有這些;我們可以推斷出,輸入數(shù)據(jù)以字符串形式輸入,但在需要時(shí)可以轉(zhuǎn)換為數(shù)值
  • 輸入 —— Awk 只是通過它的“數(shù)據(jù)轉(zhuǎn)換管道”的方式發(fā)送輸入來讀取數(shù)據(jù)
  • 輸出 —— 我們已經(jīng)使用了 Awk 的??print?? 和??printf?? 函數(shù)來將內(nèi)容寫入輸出
  • 條件判斷 —— 我們已經(jīng)學(xué)習(xí)了 Awk 的??if-then-else?? 和對(duì)應(yīng)特定輸入行配置的輸入過濾器
  • 循環(huán) —— 嗯,想象一下!我們?cè)谶@里不需要循環(huán),這還是多虧了 Awk 采用的“數(shù)據(jù)轉(zhuǎn)換管道”方法;循環(huán)“就這么發(fā)生了”。注意,用戶可以通過向 Awk 發(fā)送一個(gè)文件結(jié)束信號(hào)(當(dāng)使用 Linux 終端窗口時(shí)可通過快捷鍵??CTRL-D??)來提前退出管道。

不需要循環(huán)來處理輸入的重要性是非常值得的。Awk 能夠長期保持存在的一個(gè)原因是 Awk 程序是緊湊的,而它們緊湊的一個(gè)原因是不需要從控制臺(tái)或文件中讀取的那些格式代碼。

讓我們運(yùn)行下面這個(gè)程序:

我們沒有涉及的一件事是注釋。Awk 注釋以 ??#?? 開頭,以行尾結(jié)束。

總結(jié)

Awk 非常強(qiáng)大,這種“猜數(shù)字”游戲是入門的好方法。但這不應(yīng)該是你探索 Awk 的終點(diǎn)。你可以看看 Awk 和 Gawk(GNU Awk)的歷史,Gawk 是 Awk 的擴(kuò)展版本,如果你在電腦上運(yùn)行 Linux,可能會(huì)有這個(gè)?;蛘撸瑥乃脑奸_發(fā)者那里閱讀關(guān)于 最初版本 的各種信息。

你還可以 ??下載我們的備忘單?? 來幫你記錄下你所學(xué)的一切。


??Awk 備忘單??


責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2023-01-13 18:55:09

游戲Ada編程語言

2021-01-12 06:42:50

Lua腳本語言編程語言

2023-02-23 14:30:27

游戲Tcl

2023-02-13 08:26:28

猜數(shù)字Basic

2021-10-04 18:49:46

Fortran 77語言猜數(shù)字

2021-01-03 16:30:34

Rust編程語言

2021-01-19 09:35:36

Python視頻游戲編程語言

2021-01-01 19:30:21

Python編程語言

2021-04-13 06:35:13

Elixir語言編程語言軟件開發(fā)

2020-12-28 06:29:31

Bash互動(dòng)游戲Linux

2021-01-05 12:38:53

C++編程語言軟件開發(fā)

2018-03-29 08:30:48

Linux命令BASH

2021-01-14 08:55:20

C語言編程

2019-09-23 09:11:02

Python文本編輯器操作系統(tǒng)

2016-10-08 20:58:50

awkLinux編寫腳本

2019-10-08 15:27:18

掃雷BashLinux

2020-12-09 11:42:18

WiFi IoT鴻蒙開發(fā)

2015-09-29 09:38:50

Java程序猜大小

2021-04-22 09:57:37

Random方法游戲

2022-03-10 14:57:35

ArkUIets項(xiàng)目開發(fā)鴻蒙
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)