丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗,強烈建議使用更快更安全的瀏覽器
此為臨時鏈接,僅用于文章預覽,將在時失效
人工智能開發(fā)者 正文
發(fā)私信給恒亮
發(fā)送

0

Bash 老司機也可能忽視的 10 大編程細節(jié)

本文作者: 恒亮 2017-03-28 19:12
導語:針對 Bash 中這些極容易出錯的細節(jié),我們在這里梳理匯總了 10 條編程注意事項。

Bash 老司機也可能忽視的 10 大編程細節(jié)

雷鋒網(wǎng)按:Bash,作為大部分 Linux 發(fā)行版的出廠預設 Shell,因其晦澀難懂的語法設置,以及需要特別留心的編程細節(jié),幾乎成為 Linux 區(qū)別于其他操作系統(tǒng)的代名詞。針對 Bash 中一些極容易出錯的細節(jié),我們在這里總結了 10 條編程注意事項,希望對各位泛 Linux 環(huán)境的開發(fā)者有所裨益。原文來自一位名叫 Julia Evans 的開發(fā)者博客,雷鋒網(wǎng)編譯。

作為一名 Bash 腳本編寫經(jīng)驗超過 10 年的老程序員,我通常不用 Bash 處理復雜的編程任務。但作為一款我們在日常 Linux 使用中幾乎無法避免的通用工具,Bash 的確有許多與我們習以為常的 C++ 和 Java 等高級語言非常不同的基礎特性。在這里我并不打算討論 Bash 編程的高階應用,而是僅僅針對 Bash 中那些與眾不同的基礎特性做一簡單梳理和匯總。希望對各位有所幫助。

當然,如果你對閱讀博客不感興趣,這里我再順便推薦兩個開源免費的小工具。一個是 Shell 語法檢查工具 shellcheck,可以在運行前對腳本進行全面的語法檢查;另一個是 shfmt,可以自動對寫好的 Shell 腳本按照要求格式化。

shellcheck 地址:https://www.shellcheck.net/ 

shfmt 地址:https://github.com/mvdan/sh 

1. 等號兩邊慎用空格

Bash 中的賦值語句通常都是這樣的:

VARIABLE=2

然后我們通過 $VARIABLE 引用該變量。這里有一點非常重要,也極容易忽視的就是:千萬不要在等號兩邊加空格。雖然加上空格也不會引起語法錯誤,但很可能造成意想不到的結果。例如 VARIABLE= 2 這個語句,解釋器很可能會將一個空字符串賦值給 VARIABLE,然后運行一個名字叫 2 的腳本。

一般常用的 Bash 變量都是字符串,我很少見到有數(shù)組的。另外,雖然解釋器也接受小寫,但 Bash 中默認是將變量名全部大寫的。

2. 用 ${} 限定變量名

例如我定義了一個變量 MYVAR,內(nèi)容是字符串“file.txt”,然后想執(zhí)行如下命令:

mv $MYVAR $MYVAR__bak # wrong!

結果一定會報錯。因為解釋器會搜索 MYVAR__bak 這個變量,而我們根本沒有定義。因此,為了避免出現(xiàn)類似問題,最好的辦法是每次引用時都在變量兩邊加上括號,就像這樣:

mv ${MYVAR} ${MYVAR}__bak # right!

3. 區(qū)分全局變量、局部變量和環(huán)境變量

Bash 有三種變量:全局變量、局部變量和環(huán)境變量。其中最常用的是環(huán)境變量。

實際上每個 Linux 進程都有許多預設的環(huán)境變量(運行 env 命令可查看),Bash 中對環(huán)境的變量的應用非常簡單。例如,想要查看 MYVAR 環(huán)境變量的值,可以運行下面這條命令:

echo "$MYVAR"

想要設置環(huán)境變量,可以用這條命令:

export MYVAR=2

需要注意的是,一旦在進程中設置了環(huán)境變量,那么這個環(huán)境變量會在所有與其相關的子進程中生效,例如下面這個例子:

export MYVAR=2; python test.py

$MYVAR 環(huán)境變量也會在 test.py 腳本中生效。

另一種是全局變量,如下所示這樣的賦值語句實際上就是在定義全局變量:

MYVAR=2

全局變量就像其他編程語言一樣,會在整個代碼中生效。

最后一種是局部變量,這種變量通常只在一個循環(huán)語句或者 Bash 函數(shù)中有效。一般不常用。

4. 活用命令替換

通常我會用下面這段 for 循環(huán)打印輸出 1-10 這 10 個數(shù)字。

for i in `seq 1 10` # you can use {1..10} instead of `seq 1 10` 

do     

 echo "$i"

done

如果把這些代碼寫到一行里,是這樣的:

for i in `seq 1 10`; do echo $i; done

這里我想強調(diào)的是,通過反引號(即鍵盤上Tab鍵上方的按鍵,注意不是單引號)將 seq 命令的輸出結果,嵌入了 for 循環(huán)中直接使用。通過類似這種命令替換的方式,我們可以大大減少代碼冗余,同時減少代碼的出錯幾率。常見的替換方式有如下兩種:

OUTPUT=`command`

# or

OUTPUT=$(command)

5. if 的注意事項

if 語句的判定條件同時支持單中括號([])和雙中括號([[]]),他們都可以用來隔離表達式和 if 關鍵詞。但這里推薦使用雙中括號,因為它的容錯率更高,而且支持更多功能。另外,在 Linux 中單中括號 [ 實際與 test 命令是等價的,因此用雙括號顯然能避免更多的麻煩。

例如下面這段代碼:

If [[ -e /tmp/awesome.txt ]]; then

  echo "awesome"

fi

可以判斷 awesome.txt 文件是否存在。

再比如下面的場景:

$ [ 3 < 4 ] && echo "true"

bash: 4: No such file or directory

$ [[ 3 < 4 ]] && echo "true"

true

使用單中括號會報錯,但雙中括號就沒問題。

除了使用雙中括號之外,還可以用 test 命令的運行結果作為 if 語句的判斷條件,例如:

test -e /tmp/awesome.txt

如果 awesome.txt 文件存在,則命令返回 0,否則返回錯誤碼。

實際上,除了常見的 test 命令,所有返回固定數(shù)值的命令都可以作為 if 語句的判斷條件。例如下面的代碼:

if grep peanuts food-list.txt

then

echo "allergy allert!"

fi

利用 grep 搜索關鍵詞,然后根據(jù)結果打印警告信息。

6. 使用函數(shù)

在 Bash 中定義和使用函數(shù)非常簡單(特別是無參函數(shù))。例如:

my_function () {

 echo "This is a function"; 

}

my_function # calls the function

代碼中定義了一個 my_function 函數(shù),調(diào)用時也只需要寫函數(shù)名。

7. 用雙引號引用變量

前面第 2 條提到要用 ${} 限定變量名的范圍,這里要說的是利用引號限定變量值的范圍。

例如下面代碼:

X="i am awesome"

Y="i are awesome"

if [ $X = $Y ]; then

 echo awesome

fi

實際上會報錯,因為解釋器會將 if 語句的判定條件理解為:

if [ i am awesome == i are awesome ]

為了避免這種錯誤,就必須用雙引號限定變量值的范圍。

X="i am awesome"

Y="i are awesome"

if [ "$X" = "$Y" ]; then # i put quotes because i know bash will betray me otherwise

 echo awesome

fi

這樣寫就沒問題了。當然,如果變量值不包括空格,那不帶引號也能得到同樣的結果,但畢竟帶上雙引號會讓程序更可靠。

8. 關于返回值

每一個 Linux 程序都有返回值,按照規(guī)范,這個返回值在 0-127 之間,0 表示成功,其他值是含義各不相同的錯誤碼。在 Bash 中充分利用這一點可以增加程序的靈活性。例如:

create_user && make_home_directory

這條語句,只有 create_user 返回 0 時,才會執(zhí)行 make_home_directory。

create_user; make_home_directory

則表示無論 create_user 的返回值是什么,都會執(zhí)行 make_home_directory。

類似的,你也可以通過:

create_user || make_home_directory

表示只有當 create_user 返回非 0 值時,才會執(zhí)行 make_home_directory。

9. 使用后臺任務

在 Bash 中,可以通過在命令后添加 & 符號實現(xiàn)后臺多任務。例如:

long_running_command &

把進程放入后臺后,還可以通過 fg 命令將其切換到前臺。如果后臺命令過多,可以先通過 jobs 命令查看進程的 job ID,然后用 fg+job ID 的方式將指定的后臺進程切換到前臺。

另外,還可以通過 wait 命令控制多任務的執(zhí)行順序。例如:

long_running_command1

wait

long_running_command2

表示在命令 1 執(zhí)行結束后才執(zhí)行命令 2。

10. 活用 set 命令

在其他語言中,通常遇到錯誤的語句時,編譯器就會報錯并停止運行,但 Bash 不會。例如下面的代碼:

python non_existant_file.py

echo "done"

無論 non_existant_file.py 腳本是否存在,Bash 都會打印輸出 done。因此為了保證代碼的安全性和正確性,我們可以在代碼中用

set -e

對 Bash 環(huán)境進行一些額外設置,-e 表示出現(xiàn)錯誤就停止。

類似的,在其他語言中,使用沒初始化的變量也會報錯,但 Bash 不會。例如下面的代碼:

rm -rf "$DIRECTORY/*" 

如果 $DIRECTORY 沒有提前初始化,Bash 也并不會停下來,而是直接以空字符串對待,那么這句命令的含義就變成了:嘗試刪除根目錄下的所有文件,結果將非常嚴重。

這時就可以用 

set -u

表示 Bash 不執(zhí)行未定義的變量。

除了 -e 和 -u 之外,還有

set -x 

表示每條命令執(zhí)行之前必須先打印命令內(nèi)容。此外還可以通過 set -o 顯示所有可以設置的選項。

這也是為什么許多 shell 腳本都以 set -eu 或者 set -eux 等做為開頭的原因,因為這樣就可以讓腳本運行在更安全的環(huán)境下。

來源:jvns.ca,雷鋒網(wǎng)編譯

雷峰網(wǎng)版權文章,未經(jīng)授權禁止轉載。詳情見轉載須知。

Bash 老司機也可能忽視的 10 大編程細節(jié)

分享:
相關文章

編輯

歡迎交流,微信:whl123465
當月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個人簡介
為了您的賬戶安全,請驗證郵箱
您的郵箱還未驗證,完成可獲20積分喲!
請驗證您的郵箱
立即驗證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設置密碼以方便用郵箱登錄
立即設置 以后再說