成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

帶你了解Shell腳本編程陷阱

系統 Linux
Ruby 版本的代碼雖然不是那么長,也并不復雜。但是 shell 版是如此簡單,我甚至不用實際測試就可以確保它是正確的。而 Ruby 版的我就沒法確定它不會出錯了,必須得測試一下。而且它要長一倍,看起來也更復雜。

[[263427]]

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

  1. # 用含有 Go 的詞匯起名字:
  2. $ grep -i ^go /usr/share/dict/* | cut -d: -f2 | sort -R | head -n1
  3. goldfish

如果用其他編程語言,就需要花費更多的腦力,用多行代碼實現,比如用 Ruby 的話:

  1. puts(Dir['/usr/share/dict/*-english'].map do |f|
  2. File.open(f)
  3. .readlines
  4. .select { |l| l[0..1].downcase == 'go' }
  5. end.flatten.sample.chomp)

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

這就是人們使用 Shell 腳本的原因,它簡單卻實用。下面是另一個例子:

  1. curl https://nl.wikipedia.org/wiki/Lijst_van_Nederlandse_gemeenten |
  2. grep '^<li><a href=' |
  3. sed -r 's|<li><a href="/wiki/.+" title=".+">(.+)</a>.*</li>|\1|' |
  4. 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 編程的確存在一些實際的限制。下面是一些例子:

  • 在處理一些包含“空格”或者其他“特殊”字符的文件名時,需要特別注意細節。絕大多數腳本都會犯錯,即使是那些經驗豐富的作者(比如我)編寫的腳本,因為太容易寫錯了,只添加引號是不夠的
  • 有許多所謂“正確”和“錯誤”的做法。你應該用 which 還是 command?該用 $@ 還是 $*,是不是得加引號?你是該用 cmd $arg 還是 cmd "$arg"?等等等等。
  • 你沒法在變量里存儲空字節(0x00);shell 腳本處理二進制數據很麻煩。
  • 雖然你可以非常快速地寫出有用的東西,但實現更復雜的算法則要痛苦許多,即使用 ksh/zsh/bash 擴展也是如此。我上面那個解析 HTML 的腳本臨時用用是可以的,但你真的不會想在生產環境中使用這種腳本。
  • 很難寫出跨平臺的通用型 shell 腳本。/bin/sh 可能是 dash 或者 bash,不同的 shell 有不同的運行方式。外部工具如 grepsed 等,不一定能支持同樣的參數。你能確定你的腳本可以適用于 Linux、macOS 和 Windows 的所有版本嗎(無論是過去、現在還是將來)?
  • 調試 shell 腳本會很難,特別是你眼中的語法可能會很快變得記不清了,并不是所有人都熟悉 shell 編程的語境。
  • 處理錯誤會很棘手(檢查 $? 或是 set -e),排查一些超過“出了個小錯”級別的復雜錯誤幾乎是不可能的。
  • 除非你使用了 set -u,變量未定義將不會報錯,而這會導致一些“搞笑事件”,比如 rm -r ~/$undefined 會刪除用戶的整個家目錄(瞅瞅 Github 上的這個悲劇)。
  • 所有東西都是字符串。一些 shell 引入了數組,能用,但是語法非常丑陋和費解。帶分數的數字運算仍然難以應付,并且依賴像 bcdc 這樣的外部工具($(( .. )) 這種方式只能對付一下整數)。

反饋

你可以發郵件到 martin@arp242.net,或者在 GitHub 上創建 issue 來向我反饋,提問等。


責任編輯:龐桂玉 來源: Linux中國
相關推薦

2019-09-27 09:40:06

ElvishShellLinux

2019-03-26 10:50:22

Python面向對象編程語言

2011-09-27 13:52:41

2020-06-17 10:42:54

shellshell腳本Linux

2019-08-06 09:00:00

JavaScript函數式編程前端

2022-05-13 16:21:38

javascrip腳本SVG

2020-12-23 08:12:08

javascriptSVG腳本SVG元素

2018-06-08 08:50:35

編程語言并發編程

2020-10-21 11:55:44

Shell編程語言Linux

2022-09-26 11:30:40

MQTT協議客戶端協議

2024-11-07 16:09:53

2010-06-23 15:55:36

Linux Bash

2010-07-05 16:20:32

NetBEUI協議

2020-12-31 12:16:49

SAP云計算SAP產品

2021-02-03 16:22:43

新基建SAP

2021-05-31 14:22:56

物聯網物聯網安全

2010-09-02 16:59:35

資源預留協議

2019-11-05 10:18:04

RPM包RPMLinux

2021-12-10 10:29:07

在線客服系統

2018-03-01 16:25:52

Linux內核內存管理
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲在线日韩 | 国产精品久久久久久久久久久久久久 | 一区二区三区免费 | 亚洲精品免费观看 | 神马久久久久久久久久 | 午夜视频一区二区三区 | 国产一区二区三区在线 | 久久99视频免费观看 | 综合久久99 | 精品无码久久久久久国产 | 国产精品日本一区二区不卡视频 | 91免费观看 | 日韩免费 | 亚洲国产成人精品女人久久久 | 伊人性伊人情综合网 | a级免费黄色片 | 奇米影视首页 | 日本一级淫片免费啪啪3 | 久久久免费电影 | 久久福利电影 | 亚洲成年在线 | 日本一区二区三区视频在线 | 色婷婷精品国产一区二区三区 | 91久色 | 一区二区三区四区在线 | 成人国产一区二区三区精品麻豆 | 亚洲日本中文字幕在线 | 日本不卡一区二区 | 欧美黄色性生活视频 | 成人黄色av网址 | 日本中文字幕在线观看 | 国产一级在线观看 | 国产在线观看 | 噜啊噜在线 | 97色在线视频 | 国产高清视频在线观看 | 蜜桃视频一区二区三区 | 精品国产乱码久久久久久丨区2区 | 欧美日韩亚洲系列 | 日韩视频一级 | 超碰激情|