bash和dash的区别(及示例)

什么是bash、dash

Bash(GNU Bourne-Again Shell)是许多Linux平台的内定Shell,事实上,还有许多传统UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等。
GNU/Linux 操作系统中的 /bin/sh 本是 bash (Bourne-Again Shell) 的符号链接,但鉴于 bash 过于复杂,有人把 bash 从 NetBSD 移植到 Linux 并更名为 dash (Debian Almquist Shell),并建议将 /bin/sh 指向它,以获得更快的脚本执行速度。Dash Shell比 Bash Shell小的多,符合POSIX标准。
Debian和Ubuntu中,/bin/sh默认已经指向dash,这是一个不同于bash的shell,它主要是为了执行脚本而出现,而不是交互,它速度更快,但功能相比bash要少很多,语法严格遵守POSIX标准。

要知道自己自己的/bin/sh指向那个解析器,可使用 ls -al /bin/sh 查看

netsky@netsky:~$ ls -al /bin/sh
lrwxrwxrwx 1 root root 4 Mar 23  2022 /bin/sh -> dash

bash和dash语法区别

bash和dash语法上的主要区别有:

1. 定义函数

dash中没有function关键字,而bash可以有也可以没有function关键字

# dash这里没有function关键字,使用function,将在"("附近报语法错误
function func1(){
  echo "print func1"
}

# 该写法bash和dash均支持
func2(){
  echo "print func2"
}

func1
func2

结论:定义函数时不使用function关键字达到通用的目的。

2. select var in list; do command; done

dash不支持该写法,需要改成while read case 来实现

# dash不支持select选择语句
select animal in lion tiger panda flower; do
    if [ "$animal" = "flower" ]; then
        echo "Flower is not animal."
        break
    else
        echo "Choose animal is: $animal"
    fi
done

# bash和dash均支持while read case 写法
while true
do
  cat << EOF
 1) lion
 2) tiger
 3) panda
 4) flower
EOF
  read -p "input :" animal
  case "$animal" in
    1) echo "lion"
       ;;
    2) echo "tiger"
       ;;
    3) echo "panda"
       ;;
    *) echo "not animal"
       break
       ;;
  esac
done

结论:使用while read case写法达到通用的目的。

3. {0..10}

dash不支持{m..n}展开,识别为单个整体

# dash不支持{m..n}展开
for i in {0..10}
do
  echo $i
done

# bash和dash均支持
for i in $(seq 11)
do
  echo $i
done

结论:使用seq或者其它loop写法,为了灵活使用的话,可使用bash,并使用bash 脚本名称 的方式运行脚本。

4. here strings

dash不支持here string,改成here document

# dash不支持here strings
cat <<< "here strings"

# bash和dash均支持here document
cat << EOF
here document
EOF

结论:使用here document 达到通用的目的。

5. >&word重定向标准输出和标准错误

当word为非数字时,bash中>&word变成重定向标准错误和标准输出到word中
而dash中>&word,word不支持非数字,替代方法是: >word 2>&1

# bash支持的写法  
echo "1234" >&err1.log

# bash和dash均支持的写法
echo "5678" >err2.log 2>&1

结论:使用通用的重定向标准输入和标准错误写法。

6. 数组

bash支持数组,而dash不支持,需要替代

# bash支持的写法
array=(test001 test002 test003)
echo ${array[2]}

# bash和dash均支持的写法,需注意会替换掉传参,需及时赋值 
var="test001 test002 test003"
set -- $var
echo ${3}       # 超过10个,需注意${10}写法

结论:bash很灵活,如果需要通用,需要使用替代写法。

7. 子字符串扩展

bash支持${parameter:offset:length}等写法
而dash不支持这类扩展,替代方法是使用其它外部命令

str="Abcdefgh"

# bash和dash均支持的写法,cut从第N位开始
echo $str | cut -b 4-5

# bash支持的写法,跳过(offset)M位,从M+1位开始
echo ${str:3:2}

结论:bash很灵活,如果需要通用,需要使用替代写法。

8. 大小写转换

bash支持${parameter^pattern},${parameter^^pattern}大小写替换写法
而dash不支持这类扩展,替换方法是使用使用其它外部命令(如tr/sed/awk)

str1="abcdefgh"
str2="ABCDEFGH"

# bash和dash均支持
echo ${str1} | sed 's/^\b[a-z]/\U&/'
echo ${str2} | sed 's/^\b[A-Z]/\L&/'

echo ${str1} | tr [:lower:] [:upper:]
echo ${str2} | tr [:upper:] [:lower:]

# bash支持 ^(大写), ,(小写), ~(反转)
echo ${str1^}
echo ${str1^^}

echo ${str2,}
echo ${str2,,}

结论:bash很灵活,如果需要通用,需要使用替代写法。

9. 进程替换<(command), >(command)

bash支持进程替换
dash不支持,替代方法是使用临时文件转换

# bash和dash均支持临时文件的写法,这里只是示例
echo "test001" > 10.tmp
while read user
do
   echo $user
done < 10.tmp

# bash支持进程替换,注意 <() 是个整体
read user < <(echo "test002")
echo $user

结论:bash很灵活,如果需要通用,需要使用替代写法。

10. [ str1 = str2 ]和[ str1 == str2 ]

bash两种方法均支持
dash仅支持=写法

str="A"

# bash和dash均支持
[ $str = "A" ] && echo 1 || echo 2

# bash支持
[ $str == "A" ] && echo 11 || echo 12

结论:使用=写法达到通用的目的。

11. [[]] 加强版test

bash支持[[]] 写法,可实现正则匹配等强大功能
dash不支持该语法,需要使用替代写法。

tel=23800138000

# bash和dash均支持,使用外部命令方式
echo "$tel" | sed 's/2[0-9]\{10\}/1/'

# bash支持
[[ $tel =~ 1[0-9]{10} ]] && echo 1 || echo 2

结论:bash很灵活,如果需要通用,需要使用替代写法。

12. for ((expr1; expr2; expr 3)); do list; done

bash支持C语言格式的for循环
dash不支该语法,需要使用替代写法(如:while $((expr)))。

# bash和dash均支持
i=0
while [ $i -lt 10 ]
do
  echo $i
  i=$((i+=1))
done

# bash支持
for ((i=0;i<10;i++))
do
  echo $i
done

结论:bash很灵活,如果需要通用,需要使用替代写法。

13. let命令和((expression))

bash支持let,也支持((expression))
dash不支持,替代方法是采用$(())或者使用其它外部命令做计算

a=10

# bash和dash均支持下面两种写法  
a=$((a+=1))
echo $a

a=$(expr $a + 1)
echo $a

# bash支持let和((expression))写法 
let a++
echo $a

((a++))
echo $a

结论:bash很灵活,如果需要通用,需要使用替代写法。

14. $((expression))

bash支持i++,++i,i--这样的表达式
dash不支持++,--,替代方法是i+=1,i=i+1

a=10

# bash和dash均支持
echo $((a=a+1))

# bash支持++
echo $((a++))

结论:bash很灵活,如果需要通用,需要使用替代写法。

总结

bash相对于dash来说很灵活,有更多的语法支持。
需要通用的情况下,需要注意差异,使用符合POSIX标准的写法;如果确定能使用bash的情况下,将能更灵活使用。
需要特别注意的是:

  • 如果shell脚本是使用bash编写,但当前的/bin/sh链接到的是dash,那么"sh 脚本" 将会使用dash来执行,而忽视头部shell指示!
  • 如果shell脚本是使用bash编写,请使用"bash 脚本" 或者 "./脚本" 的方式执行脚本。

标签: bash, dash, shell, shell区别

添加新评论