• 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支持 p a r a m e t e r p a t t e r n , {parameter^pattern}, parameterpattern,{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 脚本" 或者 “./脚本” 的方式执行脚本。
  • 相关阅读:
    【由浅入深_打牢基础】HOST头攻击
    LeetCode 93. 复原 IP 地址
    开源项目-十六进制协议传感器自适应缩放曲线显示终端(百问网imx6ull & 小熊派结合)...
    7.新增类型Symbol
    计算机视觉小项目—基于RGB颜色特征的火焰识别
    vim的简单使用
    运维职业规划
    Leetcode数据库系列题解合集(持续更新)
    flv播放问题总结
    SpringBoot集成Redisson操作Redis
  • 原文地址:https://blog.csdn.net/liaosnet/article/details/139831436