Shell 指令碼程式設計陷阱

2021-09-24 08:58:29 字數 1673 閱讀 1018

shell 指令碼很棒,你可以非常輕鬆地寫出有用的東西來。甚至像是下面這個傻瓜式的命令:

# 用含有 go 的詞彙起名字:

$ grep -i ^go /usr/share/dict/* | cut -d: -f2 | sort -r | head -n1

goldfish

複製**

puts(dir['/usr/share/dict/*-english'].map do |f|

file.open(f)

.readlines

.select

end.flatten.sample.chomp)

複製**

ruby 版本的**雖然不是那麼長,也並不複雜。但是 shell 版是如此簡單,我甚至不用實際測試就可以確保它是正確的。而 ruby 版的我就沒法確定它不會出錯了,必須得測試一下。而且它要長一倍,看起來也更複雜。

這就是人們使用 shell 指令碼的原因,它簡單卻實用。下面是另乙個例子:

curl  |

grep '^|

sed -r 's|(.+).*|\1|' |

grep -ev '(^tabel van|^lijst van|nederland)'

複製**

這個指令碼可以從維基百科上獲取荷蘭基層政權的列表。幾年前我寫了這個臨時的指令碼,用來快速生成乙個資料庫,到現在它仍然可以正常執行,當時寫它並沒有花費我多少精力。但要用 ruby 完成同樣的功能則會麻煩得多。

現在來說說 shell 的缺點吧。隨著**量的增加,你的指令碼會變得越來越難以維護,但你也不會想用別的語言重寫一遍,因為你已經在這個 shell 版上花費了很多時間。

我把這種情況稱為「shell 指令碼程式設計陷阱」,這是沉沒成本謬論的一種特例(lctt 譯註:「沉沒成本謬論」是乙個經濟學概念,可以簡單理解為,對已經投入的成本可能被浪費而念念不忘)。

實際上許多指令碼會增長到超出預期的大小,你經常會花費過多的時間來「修復某個 bug」,或者「新增乙個小功能」。如此迴圈往復,讓人頭大。

如果你從一開始就使用 python、ruby 或是其他類似的語言來寫這個程式,你可能會在寫第一版的時候多花些時間,但以後維護起來就容易很多,bug 也肯定會少很多。

以我的 packman.vim 指令碼為例。它起初只包含乙個簡單的用來遍歷所有目錄的for迴圈,外加乙個git pull,但在這之後就剎不住車了,它現在有 200 行左右的**,這肯定不能算是最複雜的指令碼,但假如我一上來就按計畫用 go 來編寫它的話,那麼增加一些像「列印狀態」或者「從配置檔案裡轉殖新的 git 庫」這樣的功能就會輕鬆很多;新增「並行轉殖」的支援也幾乎不算個事兒了,而在 shell 指令碼裡卻很難實現(儘管不是不可能)。事後看來,我本可以節省時間,並且獲得更好的結果。

出於類似的原因,我很後悔寫出了許多這樣的 shell 指令碼,而我在 2018 年的新年誓言就是不要再犯類似的錯誤了。

需要指出的是,shell 程式設計的確存在一些實際的限制。下面是一些例子:

反饋

你可以發郵件到 [email protected],或者在 github 上建立 issue 來向我反饋,提問等。

via: arp242.net/weblog/shel…

本文由 lctt 原創編譯,linux中國 榮譽推出

Shell 指令碼程式設計

1 執行shell的方法 指定shell bin sh 由sh執行指令碼 指令碼總是由sh解釋 顯示呼叫shell sh scriptname 在當前shell中執行指令碼 profile profile是可執行的 ksh profile profile是不可執行的 改變當前的執行環境責應輸入.pr...

Shell 指令碼程式設計

a file 如果 file 存在則為真。b file 如果 file 存在且是乙個塊特殊檔案則為真。c file 如果 file 存在且是乙個字特殊檔案則為真。d file 如果 file 存在且是乙個目錄則為真。e file 如果 file 存在則為真。f file 如果 file 存在且是乙個...

shell指令碼程式設計

今天看看shell程式設計,記錄下期中與想象中不一樣的地方 0.注釋用 1.shell的變數賦值 your name zhm 在your name和等號中間不能有空格,這和別的語言很不一樣,那麼在使用變數時和別的語言也不一樣,要使用 your name,一般要用 一定是大括號 2.那麼如何把乙個變數...