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

怎樣用Bash編程:語法和工具

系統(tǒng) Linux 后端
讓我們通過本系列文章來學(xué)習(xí)基本的 Bash 編程語法和工具,以及如何使用變量和控制運(yùn)算符,這是三篇中的第一篇。

怎樣用Bash編程:語法和工具

讓我們通過本系列文章來學(xué)習(xí)基本的 Bash 編程語法和工具,以及如何使用變量和控制運(yùn)算符,這是三篇中的第一篇。

Shell 是操作系統(tǒng)的命令解釋器,其中 Bash 是我最喜歡的。每當(dāng)用戶或者系統(tǒng)管理員將命令輸入系統(tǒng)的時候,Linux 的 shell 解釋器就會把這些命令轉(zhuǎn)換成操作系統(tǒng)可以理解的形式。而執(zhí)行結(jié)果返回 shell 程序后,它會將結(jié)果輸出到 STDOUT(標(biāo)準(zhǔn)輸出),默認(rèn)情況下,這些結(jié)果會顯示在你的終端。所有我熟悉的 shell 同時也是一門編程語言。

Bash 是個功能強(qiáng)大的 shell,包含眾多便捷特性,比如:tab 補(bǔ)全、命令回溯和再編輯、別名等。它的命令行默認(rèn)編輯模式是 Emacs,但是我最喜歡的 Bash 特性之一是我可以將其更改為 Vi 模式,以使用那些儲存在我肌肉記憶中的的編輯命令。

然而,如果你把 Bash 當(dāng)作單純的 shell 來用,則無法體驗(yàn)它的真實(shí)能力。我在設(shè)計(jì)一套包含三卷的 Linux 自學(xué)課程時(這個系列的文章正是基于此課程),了解到許多 Bash 的知識,這些是我在過去 20 年的 Linux 工作經(jīng)驗(yàn)中所沒有掌握的,其中的一些知識就是關(guān)于 Bash 的編程用法。不得不說,Bash 是一門強(qiáng)大的編程語言,是一個能夠同時用于命令行和 shell 腳本的完美設(shè)計(jì)。

本系列文章將要探討如何使用 Bash 作為命令行界面(CLI)編程語言。第一篇文章簡單介紹 Bash 命令行編程、變量以及控制運(yùn)算符。其他文章會討論諸如:Bash 文件的類型;字符串、數(shù)字和一些邏輯運(yùn)算符,它們能夠提供代碼執(zhí)行流程中的邏輯控制;不同類型的 shell 擴(kuò)展;通過 for、whileuntil 來控制循環(huán)操作。

Shell

Bash 是 Bourne Again Shell 的縮寫,因?yàn)?Bash shell 是 基于 更早的 Bourne shell,后者是 Steven Bourne 在 1977 年開發(fā)的。另外還有很多其他的 shell 可以使用,但下面四個是我經(jīng)常見到的:

  • csh:C shell 適合那些習(xí)慣了 C 語言語法的開發(fā)者。
  • ksh:Korn shell,由 David Korn 開發(fā),在 Unix 用戶中更流行。
  • tcsh:一個 csh 的變種,增加了一些易用性。
  • zsh:Z shell,集成了許多其他流行 shell 的特性。

所有 shell 都有內(nèi)置命令,用以補(bǔ)充或替代核心工具集。打開 shell 的 man 說明頁,找到“BUILT-INS”那一段,可以查看都有哪些內(nèi)置命令。

每種 shell 都有它自己的特性和語法風(fēng)格。我用過 csh、ksh 和 zsh,但我還是更喜歡 Bash。你可以多試幾個,尋找更適合你的 shell,盡管這可能需要花些功夫。但幸運(yùn)的是,切換不同 shell 很簡單。

所有這些 shell 既是編程語言又是命令解釋器。下面我們來快速瀏覽一下 Bash 中集成的編程結(jié)構(gòu)和工具。

作為編程語言的 Bash

大多數(shù)場景下,系統(tǒng)管理員都會使用 Bash 來發(fā)送簡單明了的命令。但 Bash 不僅可以輸入單條命令,很多系統(tǒng)管理員可以編寫簡單的命令行程序來執(zhí)行一系列任務(wù),這些程序可以作為通用工具,能節(jié)省時間和精力。

編寫 CLI 程序的目的是要提高效率(做一個“懶惰的”系統(tǒng)管理員)。在 CLI 程序中,你可以用特定順序列出若干命令,逐條執(zhí)行。這樣你就不用盯著顯示屏,等待一條命令執(zhí)行完,再輸入另一條,省下來的時間就可以去做其他事情了。

什么是“程序”?

自由在線計(jì)算機(jī)詞典(FOLDOC)對于程序的定義是:“由計(jì)算機(jī)執(zhí)行的指令,而不是運(yùn)行它們的物理硬件。”普林斯頓大學(xué)的 WordNet 將程序定義為:“……計(jì)算機(jī)可以理解并執(zhí)行的一系列指令……”維基百科上也有一條不錯的關(guān)于計(jì)算機(jī)程序的條目。

總結(jié)下,程序由一條或多條指令組成,目的是完成一個具體的相關(guān)任務(wù)。對于系統(tǒng)管理員而言,一段程序通常由一系列的 shell 命令構(gòu)成。Linux 下所有的 shell (至少我所熟知的)都有基本的編程功能,Bash 作為大多數(shù) linux 發(fā)行版的默認(rèn) shell,也不例外。

本系列用 Bash 舉例(因?yàn)樗鼰o處不在),假如你使用一個不同的 shell 也沒關(guān)系,盡管結(jié)構(gòu)和語法有所不同,但編程思想是相通的。有些 shell 支持某種特性而其他 shell 則不支持,但它們都提供編程功能。Shell 程序可以被存在一個文件中被反復(fù)使用,或者在需要的時候才創(chuàng)建它們。

簡單 CLI 程序

最簡單的命令行程序只有一或兩條語句,它們可能相關(guān),也可能無關(guān),在按回車鍵之前被輸入到命令行。程序中的第二條語句(如果有的話)可能取決于第一條語句的操作,但也不是必須的。

這里需要特別講解一個標(biāo)點(diǎn)符號。當(dāng)你在命令行輸入一條命令,按下回車鍵的時候,其實(shí)在命令的末尾有一個隱含的分號(;)。當(dāng)一段 CLI shell 程序在命令行中被串起來作為單行指令使用時,必須使用分號來終結(jié)每個語句并將其與下一條語句分開。但 CLI shell 程序中的最后一條語句可以使用顯式或隱式的分號。

一些基本語法

下面的例子會闡明這一語法規(guī)則。這段程序由單條命令組成,還有一個顯式的終止符:

  1. [student@studentvm1 ~]$ echo "Hello world." ;
  2. Hello world.

看起來不像一個程序,但它確是我學(xué)習(xí)每個新編程語言時寫下的第一個程序。不同語言可能語法不同,但輸出結(jié)果是一樣的。

讓我們擴(kuò)展一下這段微不足道卻又無所不在的代碼。你的結(jié)果可能與我的有所不同,因?yàn)槲业募夷夸浻悬c(diǎn)亂,而你可能是在 GUI 桌面中第一次登錄賬號。

  1. [student@studentvm1 ~]$ echo "My home directory." ; ls ;
  2. My home directory.
  3. chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
  4. chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
  5. TestFile1 Desktop dmesg.txt link3 Public testdir Videos
  6. TestFile1.dos dmesg1.txt Documents Music random.txt testdir1

現(xiàn)在是不是更明顯了。結(jié)果是相關(guān)的,但是兩條語句彼此獨(dú)立。你可能注意到我喜歡在分號前后多輸入一個空格,這樣會讓代碼的可讀性更好。讓我們再運(yùn)行一遍這段程序,這次不要帶結(jié)尾的分號:

  1. [student@studentvm1 ~]$ echo "My home directory." ; ls

輸出結(jié)果沒有區(qū)別。

關(guān)于變量

像所有其他編程語言一樣,Bash 支持變量。變量是個象征性的名字,它指向內(nèi)存中的某個位置,那里存著對應(yīng)的值。變量的值是可以改變的,所以它叫“變~量”。

Bash 不像 C 之類的語言,需要強(qiáng)制指定變量類型,比如:整型、浮點(diǎn)型或字符型。在 Bash 中,所有變量都是字符串。整數(shù)型的變量可以被用于整數(shù)運(yùn)算,這是 Bash 唯一能夠處理的數(shù)學(xué)類型。更復(fù)雜的運(yùn)算則需要借助 bc 這樣的命令,可以被用在命令行編程或者腳本中。

變量的值是被預(yù)先分配好的,這些值可以用在命令行編程或者腳本中??梢酝ㄟ^變量名字給其賦值,但是不能使用 $ 符開頭。比如,VAR=10 這樣會把 VAR 的值設(shè)為 10。要打印變量的值,你可以使用語句 echo $VAR。變量名必須以文本(即非數(shù)字)開始。

Bash 會保存已經(jīng)定義好的變量,直到它們被取消掉。

下面這個例子,在變量被賦值前,它的值是空(null)。然后給它賦值并打印出來,檢驗(yàn)一下。你可以在同一行 CLI 程序里完成它:

  1. [student@studentvm1 ~]$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
  2.  
  3. Hello World
  4. [student@studentvm1 ~]$

注意:變量賦值的語法非常嚴(yán)格,等號(=)兩邊不能有空格。

那個空行表明了 MyVar 的初始值為空。變量的賦值和改值方法都一樣,這個例子展示了原始值和新的值。

正如之前說的,Bash 支持整數(shù)運(yùn)算,當(dāng)你想計(jì)算一個數(shù)組中的某個元素的位置,或者做些簡單的算術(shù)運(yùn)算,這還是挺有幫助的。然而,這種方法并不適合科學(xué)計(jì)算,或是某些需要小數(shù)運(yùn)算的場景,比如財(cái)務(wù)統(tǒng)計(jì)。這些場景有其它更好的工具可以應(yīng)對。

下面是個簡單的算術(shù)題:

  1. [student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
  2. Result = 63

好像沒啥問題,但如果運(yùn)算結(jié)果是浮點(diǎn)數(shù)會發(fā)生什么呢?

  1. [student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1/Var2))"
  2. Result = 0
  3. [student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var2/Var1))"
  4. Result = 1
  5. [student@studentvm1 ~]$

結(jié)果會被取整。請注意運(yùn)算被包含在 echo 語句之中,其實(shí)計(jì)算在 echo 命令結(jié)束前就已經(jīng)完成了,原因是 Bash 的內(nèi)部優(yōu)先級。想要了解詳情的話,可以在 Bash 的 man 頁面中搜索 “precedence”。

控制運(yùn)算符

Shell 的控制運(yùn)算符是一種語法運(yùn)算符,可以輕松地創(chuàng)建一些有趣的命令行程序。在命令行上按順序?qū)讉€命令串在一起,就變成了最簡單的 CLI 程序:

  1. command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;

只要不出錯,這些命令都能順利執(zhí)行。但假如出錯了怎么辦?你可以預(yù)設(shè)好應(yīng)對出錯的辦法,這就要用到 Bash 內(nèi)置的控制運(yùn)算符, &&||。這兩種運(yùn)算符提供了流程控制功能,使你能改變代碼執(zhí)行的順序。分號也可以被看做是一種 Bash 運(yùn)算符,預(yù)示著新一行的開始。

&& 運(yùn)算符提供了如下簡單邏輯,“如果 command1 執(zhí)行成功,那么接著執(zhí)行 command2。如果 command1 失敗,就跳過 command2。”語法如下:

  1. command1 && command2

現(xiàn)在,讓我們用命令來創(chuàng)建一個新的目錄,如果成功的話,就把它切換為當(dāng)前目錄。確保你的家目錄(~)是當(dāng)前目錄,先嘗試在 /root 目錄下創(chuàng)建,你應(yīng)該沒有權(quán)限:

  1. [student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir/ && cd $Dir
  2. mkdir: cannot create directory '/root/testdir/': Permission denied
  3. [student@studentvm1 ~]$

上面的報(bào)錯信息是由 mkdir 命令拋出的,因?yàn)閯?chuàng)建目錄失敗了。&& 運(yùn)算符收到了非零的返回碼,所以 cd 命令就被跳過,前者阻止后者繼續(xù)運(yùn)行,因?yàn)閯?chuàng)建目錄失敗了。這種控制流程可以阻止后面的錯誤累積,避免引發(fā)更嚴(yán)重的問題。是時候講點(diǎn)更復(fù)雜的邏輯了。

當(dāng)一段程序的返回碼大于零時,使用 || 運(yùn)算符可以讓你在后面接著執(zhí)行另一段程序。簡單語法如下:

  1. command1 || command2

解讀一下,“假如 command1 失敗,執(zhí)行 command2”。隱藏的邏輯是,如果 command1 成功,跳過 command2。下面實(shí)踐一下,仍然是創(chuàng)建新目錄:

  1. [student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir || echo "$Dir was not created."
  2. mkdir: cannot create directory '/root/testdir': Permission denied
  3. /root/testdir was not created.
  4. [student@studentvm1 ~]$

正如預(yù)期,因?yàn)槟夸洘o法創(chuàng)建,第一條命令失敗了,于是第二條命令被執(zhí)行。

&&|| 兩種運(yùn)算符結(jié)合起來才能發(fā)揮它們的最大功效。請看下面例子中的流程控制方法:

  1. 前置 commands ; command1 && command2 || command3 ; 跟隨 commands

語法解釋:“假如 command1 退出時返回碼為零,就執(zhí)行 command2,否則執(zhí)行 command3。”用具體代碼試試:

  1. [student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
  2. mkdir: cannot create directory '/root/testdir': Permission denied
  3. /root/testdir was not created.
  4. [student@studentvm1 ~]$

現(xiàn)在我們再試一次,用你的家目錄替換 /root 目錄,你將會有權(quán)限創(chuàng)建這個目錄了:

  1. [student@studentvm1 ~]$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
  2. [student@studentvm1 testdir]$

command1 && command2 這樣的控制語句能夠運(yùn)行的原因是,每條命令執(zhí)行完畢時都會給 shell 發(fā)送一個返回碼,用來表示它執(zhí)行成功與否。默認(rèn)情況下,返回碼為 0 表示成功,其他任何正值表示失敗。一些系統(tǒng)管理員使用的工具用值為 1 的返回碼來表示失敗,但其他很多程序使用別的數(shù)字來表示失敗。

Bash 的內(nèi)置變量 $? 可以顯示上一條命令的返回碼,可以在腳本或者命令行中非常方便地檢查它。要查看返回碼,讓我們從運(yùn)行一條簡單的命令開始,返回碼的結(jié)果總是上一條命令給出的。

  1. [student@studentvm1 testdir]$ ll ; echo "RC = $?"
  2. total 1264
  3. drwxrwxr-x 2 student student 4096 Mar 2 08:21 chapter25
  4. drwxrwxr-x 2 student student 4096 Mar 21 15:27 chapter26
  5. -rwxr-xr-x 1 student student 92 Mar 20 15:53 TestFile1
  6. drwxrwxr-x. 2 student student 663552 Feb 21 14:12 testdir
  7. drwxr-xr-x. 2 student student 4096 Dec 22 13:15 Videos
  8. RC = 0
  9. [student@studentvm1 testdir]$

在這個例子中,返回碼為零,意味著命令執(zhí)行成功了?,F(xiàn)在對 root 的家目錄測試一下,你應(yīng)該沒有權(quán)限:

  1. [student@studentvm1 testdir]$ ll /root ; echo "RC = $?"
  2. ls: cannot open directory '/root': Permission denied
  3. RC = 2
  4. [student@studentvm1 testdir]$

本例中返回碼是 2,表明非 root 用戶沒有權(quán)限進(jìn)入這個目錄。你可以利用這些返回碼,用控制運(yùn)算符來改變程序執(zhí)行的順序。

總結(jié)

本文將 Bash 看作一門編程語言,并從這個視角介紹了它的簡單語法和基礎(chǔ)工具。我們學(xué)習(xí)了如何將數(shù)據(jù)輸出到 STDOUT,怎樣使用變量和控制運(yùn)算符。在本系列的下一篇文章中,將會重點(diǎn)介紹能夠控制指令執(zhí)行流程的邏輯運(yùn)算符。 

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

2019-12-26 12:47:10

BashLinux命令

2019-12-18 09:45:24

BashshellLinux

2019-11-20 12:30:21

Python編程語言語音識別

2018-04-11 09:30:16

Linux硬盤分區(qū)parted

2016-11-11 20:54:37

2013-02-26 10:05:16

vmwareAWSOpenStack

2016-12-22 10:44:30

數(shù)據(jù)分析找對象大數(shù)據(jù)

2009-12-02 16:08:51

linux系統(tǒng)

2013-04-08 10:54:51

Javascript

2009-06-01 09:34:22

2011-01-21 13:41:09

Sendmail

2015-08-27 10:02:59

2020-02-27 14:58:03

LinuxBash編程命令

2010-04-16 10:38:49

CPU消耗

2009-11-26 17:03:24

Open Suse打印

2023-07-05 14:42:40

Python字符串

2010-08-26 10:42:29

ADSL ModemDHCP服務(wù)器

2014-03-06 14:39:58

2020-03-30 14:13:15

可視化工具數(shù)據(jù)可視化

2022-03-07 09:20:00

JavaScripThree.jsNFT
點(diǎn)贊
收藏

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