
在嘗試破解目前公司前員工編寫的一些腳本時,在許多腳本中,我遇到了以下語句,這些語句將變數分配給某些命令,如下所示:
CAT=cat
GREP=grep
SED=sed
在腳本的後面,我看到他們使用了這些變數而不是常規命令:
$GREP -v "^#" `dirname $0`/abcdfilename | while read line
do
<some loop operations>
done
我不明白使用這個變數而不是grep
直接使用有什麼意義。我的問題是:
- 以這種方式執行 grep 或 sed (在我們的例子中)有什麼意義嗎?
- 這是某人試圖編寫腳本以使其他人更難以理解的結果嗎?
- 或者這只是糟糕腳本的一個例子?
答案1
標準命令在系統上有不同的實作。與 Solaris 10 及更早版本一樣,您擁有/bin/sh
舊的 Bourne shell 和/usr/xpg4/bin/sh
POSIX 相容 shell。或在 OSX 上,呼叫時使用 BSD sed sed
,呼叫時使用 GNU sed gsed
。您可以選擇要在腳本中使用的實作。
因此,當您使用變數時,更改腳本中的實作會更容易。當您需要 GNU sed 時:
SED=gsed
如果您不使用變量,則必須替換sed
腳本中所有出現的 。儘管您可以輕鬆做到這一點,但這被認為是不好的程式設計習慣。
答案2
有一種觀點認為,將整個腳本中重複使用的幾乎所有內容都變成變量,因為這樣您就可以重新定義它一次,並讓它影響腳本的其餘部分。
您可能會說,使用簡單的 sed 搜尋/替換基本上可以完成相同的事情,但許多用戶對搜尋/替換持謹慎態度,因為意外替換您不打算替換的內容並不難。
事實上,我建議對他們現有的版本進行這樣的改進:
GREP=${GREP:-/bin/grep}
這表示 GREP 將被設定為使用者在 shell 中設定的任何內容,或者如果未設置,則設定為 /bin/grep
這樣用戶就可以即時覆蓋「grep」。
$ export GREP=/bin/fgrep
$ ./path/to/script.sh
答案3
這可能是過早優化的一個例子。
該機器有多少種選擇,或者任何機器有用於sed,grep, 和awk?我敢打賭普遍平均值接近 1.0。給定特定機器上的兩個選擇,實現不同導致腳本在 PATH 上找到的版本失敗而與另一個版本一起工作的可能性有多大?如果確實發生這種情況,解決方案更有可能是更改腳本還是路徑?如果改變腳本被證明是答案,那麼找到至少一次呼叫的可能性有多大?grep代替$GREP?此套牌的堆疊不需要任何間接的需要,並且在需要時也可以按預期工作。
我不會對抗這種文化。如果您的商店有一些偏好$GREP或者/usr/bin/grep要不就grep,我可能會一起去相處。否則,KISS:避免間接,直到需要它出現為止。