常見的各種shell及其區別
引子
for((i=1;i<=10;i++));
do
echo $(expr $i \* 3 + 1);
done
網上搜到的 shell for循環腳本,別人都能正常運行,我卻報錯:
Syntax error: Bad for loop variable
究竟是怎么回事呢?
shell簡介
Shell 既是一種腳本編程語言,也是一個連接內核和用戶的軟件。在 Linux 發展的早期,唯一能用的工具就是 Shell,Linux 用戶都是在 Shell 中輸入文本命令,并查看文本輸出;如果有必要的話,Shell 也能顯示一些基本的圖形。常見的 Shell 有 sh、bash、csh、tcsh、ash、dash、zsh 等。
各種shell
-
Bourne shell (sh) UNIX 最初使用,且在每種 UNIX 上都可以使用。在 shell 編程方面相當優秀,但在處理與用戶的交互方面做得不如其他幾種shell。 sh 的全稱是 Bourne shell,由 AT&T 公司的 Steve Bourne開發,為了紀念他,就用他的名字命名了。
-
C shell (csh) csh,一個語法上接近于C語言的shell。 sh 之后另一個廣為流傳的 shell 是由柏克萊大學的 Bill Joy 設計的,這個 shell 的語法有點類似C語言,所以才得名為 C shell ,簡稱為 csh。
-
Korn shell (ksh) 完全向上兼容 Bourne shell 并包含了 C shell 的很多特性。
-
Bourne Again shell (bash) 因為Linux 操作系統缺省的 shell。即 bash 是 Bourne shell 的擴展,與 Bourne shell 完全向后兼容。在 Bourne shell 的基礎上增加、增強了很多特性。可以提供如命令補全、命令編輯和命令歷史表等功能。包含了很多 C shell 和 Korn shell 中的優點,有靈活和強大的編程接口,同時又有很友好的用戶界面。
-
Debian Almquist shell (dash) 原來bash是GNU/Linux 操作系統中的 /bin/sh 的符號連接,但由于bash過于復雜,有人把 bash 從 NetBSD 移植到 Linux 并更名為 dash,且/bin/sh符號連接到dash。Dash Shell 比 Bash Shell 小的多(ubuntu16.04上,bash大概1M,dash只有150K),符合POSIX標準。Ubuntu 6.10開始默認是Dash。
-
zsh zsh配置復雜,所以很多人都不會使用。直到有一天出了Oh My Zsh項目(https://github.com/robbyrussell/oh-my-zsh),才讓更多人發現并開始使用zsh。有人說zsh是終極shell。zsh很漂亮,很炫酷,以前是極客使用,現在小白通過oh-my-zsh可以炫耀。
規范和建議
#!
是一個特殊標記,讀作 Shebang,說明這是一個可執行的腳本。除了第一行,其他以#開頭的都不再生效,為注釋。#!
后面是腳本的解釋器程序路徑。這個程序可以是shell,程序語言或者其他通用程序,常用的是bash、sh。
Shebang標記為 #!/bin/sh
的腳本不應使用任何 POSIX 沒有規定的特性 (如 let 等命令, 但 #!/bin/bash
可以)。bash支持的寫法比dash(ubuntu中的sh)多很多。想要支持 sh xx.sh 運行的,必須遵照 POSIX 規范去寫。想要腳本寫法多樣化,不需要考慮效率的,可以將文件頭定義為 #!/bin/bash , 而且不要使用 sh xx.sh 這種運行方式。 要么就更換 sh 的軟鏈接。
關于Shebang:Linux中的二進制可執行文件和腳本可執行文件及Shebang
bash 與 dash 的區別
語法上的主要的區別有:
1. 定義函數
bash: function在bash中為關鍵字
dash: dash中沒有function這個關鍵字
2. select var in list; do command; done
bash:支持
dash:不支持, 替代方法:采用while+read+case來實現
3. echo {0…10}
bash:支持{n…m}展開
dash:不支持,替代方法, 采用seq外部命令
4. here string
bash:支持here string
dash:不支持, 替代方法:可采用here documents
5. >&word重定向標準輸出和標準錯誤
bash: 當word為非數字時,>&word變成重定向標準錯誤和標準輸出到文件word
dash: >&word, word不支持非數字, 替代方法: >word 2>&1; 常見用法 >/dev/null 2>&1
6. 數組
bash: 支持數組, bash4支持關聯數組
dash: 不支持數組,替代方法, 采用變量名+序號來實現類似的效果
7. 子字符串擴展
bash: 支持parameter:offset:length,parameter:offset:length,{parameter:offset}
dash: 不支持, 替代方法:采用expr或cut外部命令代替
8. 大小寫轉換
bash: 支持parameterpattern,parameterpattern,{parameter^^pattern},parameter,pattern,parameter,pattern,{parameter,pattern}
dash: 不支持,替代方法:采用tr/sed/awk等外部命令轉換
9. 進程替換<(command), >(command)
bash: 支持進程替換
dash: 不支持, 替代方法, 通過臨時文件中轉
10. [ string1 = string2 ] 和 [ string1 == string2 ]
bash: 支持兩者
dash: 只支持=
11. [[ 加強版test
bash: 支持[[ ]], 可實現正則匹配等強大功能
dash: 不支持[[ ]], 替代方法,采用外部命令
12. for (( expr1 ; expr2 ; expr3 )) ; do list ; done
bash: 支持C語言格式的for循環
dash: 不支持該格式的for, 替代方法,用while+((expression))實現13.let命令和((expression))bash:有內置命令let,也支持((expression))方式dash:不支持,替代方法,采用((expression))實現13.let命令和((expression))bash:有內置命令let,也支持((expression))方式dash:不支持,替代方法,采用((expression))或者外部命令做計算
14. $((expression))
bash: 支持id++,id–,++id,–id這樣到表達式
dash: 不支持++,–, 替代方法:id+=1,id-=1, id=id+1,id=id-1
15. 其它常用命令
bash: 支持 echo -e, 支持 declare
dash: 不支持。
更換sh軟鏈接
由于在 ubuntu 16.04 之后,sh
命令默認是 dash,相對于 bash 缺少了許多語法支持,我們要么像之前說的那樣,使用 Shebang #!/bin/bash
來指定 shell 腳本的解釋器,要么就直接更換掉 sh
命令的軟鏈接。筆者測試系統為 ubuntu 18.04。
我們可以通過 cat /etc/shells
來查看本機支持的 shell 類型,通過 cat /etc/passwd
來查看目前 sh
命令的默認設置(一般在輸出的第一行)。
我們也可以通過 tpye
命令來查看一下本機的 sh
命令執行的是哪個文件:
type sh
# 輸出為:sh is hashed (/bin/sh)
不出所料,就是 /bin/sh
,然后我們用 file
命令查看該文件指向的軟鏈接:
file /bin/sh
# 輸出為:/bin/sh: symbolic link to dash
果然,默認是 dash。這使得我們很多語法不能支持(詳見上一小節),我們這里直接將其軟鏈接修改到 /bin/bash
。我們可以先查看一下 /bin
目錄下存在的 shell:
ls -l /bin | grep sh
# 輸出:
# -rwxr-xr-x 1 root root 1113504 6月 7 2019 bash
# -rwxr-xr-x 1 root root 121432 1月 25 2018 dash
# lrwxrwxrwx 1 root root 4 12月 10 2020 rbash -> bash
# lrwxrwxrwx 1 root root 4 12月 10 2020 sh -> dash
# lrwxrwxrwx 1 root root 4 12月 10 2020 sh.distrib -> dash
# lrwxrwxrwx 1 root root 7 9月 18 2020 static-sh -> busybox
可以看到 dash 和 bash 都有,但是現在 sh
命令是指向 dash 的,好了,我們現在來修改軟鏈接:
sudo ln -snf bash sh
現在再來試一下之前的循環腳本,就可以直接運行了。
Ref:
https://www.huoxiaoqiang.com/experience/linux/1077.html
https://www.cnblogs.com/macrored/p/11548347.html