Ubuntu:shell脚本运行异常, bash和dash的区别, sh和bash的区别, bash、dash与zsh shell, source、sh、bash、./执行脚本的区别

今天想运行一下非常简单的代码:test.sh

#!/bin/bash
 
str="Learn to Split a String in Bash Scripting"
 
IFS=' '        # space is set as delimiter
read -ra ADDR <<< "$str"    # str is read into an array as tokens separated by IFS
for i in "${ADDR[@]}"; do    # access each element of array
    echo "$i"
done

作用就是分割字符串,然后打印出来,平时我喜欢用 sh 来执行

sh test.sh

直接报错

test.sh: 6: test.sh: Syntax error: redirection unexpected

但是用 bash 或者 ./ 来运行就没有问题:

./test.sh

#或者
bash test.sh

#结果:
Learn
to
Split
a
String
in
Bash
Scripting

然后查了一下他们的区别,如下:

sh是一个shell
如果我直接运行./a.sh,首先你会查找脚本第一行是否指定了解释器,如果没指定,那么就用当前系统默认的shell(大多数linux默认是bash),如果指定了解释器,那么就将该脚本交给指定的解释器

比如a.run文件内容是这个:

#!/usr/bin/python
print("This is Python script")

那么你如果运行./a.run,结果就是输出一行文字,但是如果你运行sh a.run,会报错

[justcode@localhost tmp]$ ./a.run 
This is Python Script
[justcode@localhost tmp]$ sh a.run 
a.run: line 2: syntax error near unexpected token `"This is Python Script"'
a.run: line 2: `print("This is Python Script")'
因为这是一个python脚本,sh看不懂(注意,linux下后缀通常不是很严格,.run后缀是我随意命名的,和windows有点区别).
我写了一个shell脚本,./a.sh和sh a.sh区别,这个要看你系统默认shell和脚本了,如果你写的是一个sh ( Bourne shell )脚本而且第一行申明了解释器为sh,那么没区别,但是如果你写的是一个bash(Bourne Again SHell) 脚本,那结果就可能有区别了,因为bash和sh的内置命令、语法等有些不一样

 

现在看一下,你正在使用的 sh 是什么shell

[justcode@localhost tmp]$ ls -al `which sh`
lrwxrwxrwx 1 root root 4 Jul 28  2016 /bin/sh -> dash
[justcode@localhost ~]$ echo $SHELL
/bin/bash

 

也就是说,我是用的 sh 其实是 dash shell,它跟 bash shell 还是有区别的,我的默认shell是bash shell

bash shell是几乎所有Linux发行版的默认shell。作为标准Unix shell——Bourne shell(沿用创建者的名字)的替代,bash shell由GNU工程开发。bash shell的名称就是针对这个Bourne shell的文字游戏,全称为“Bourne again shell”。 bash有很灵活和强大的编程接口,同时又有很友好的用户界面。功能包括命令补齐、通配符、命令历史记录、别名等。

dash shell是作为Debian Linux发行版的一部分开发的,主要出现在Ubuntu Linux发行版中。它是Bourne shell的精简版,支持的功能不像bash shell支持的那样多,这可能会给脚本编程带来一些问题。

dash shell的历史很有趣。它是ash shell的直系后代,而ash shell是Unix系统上原来的Bourne shell的简化版本。令人不解的是,实际上dash shell在许多基于Debian的Linux发行版中并不是默认的shell。由于bash shell在Linux中的流行,大多数基于Debian的Linux发行版将bash shell用作普通登录shell,只将dash shell用作安装脚本的快速启动shell来安装发行版文件。而流行的Ubuntu发行版是一个例外。Ubuntu Linux发行版将bash shell用作默认的交互shell,但将dash shell用作默认的/bin/sh shell。这通常会让shell脚本程序员很困惑,并给在Linux环境中运行shell脚本带来了很多问题。

zsh(Z shell)是另一个流行的shell,是由Paul Falstad开发的开源Unix shell。它集成了所有现有shell的思想并增加了许多独到的功能,为程序员创建了一个全功能的高级shell。zsh shell具有三大功能:改进的shell选项处理、shell兼容性模式以及可加载模块。其中,可加载模块是shell设计中最先进的功能。

如果要修改默认的sh,可以采用命令

sudo dpkg-reconfigure dash

然后选择【否】

Ubuntu:shell脚本运行异常, bash和dash的区别, sh和bash的区别, bash、dash与zsh shell, source、sh、bash、./执行脚本的区别
Ubuntu:shell脚本运行异常, bash和dash的区别, sh和bash的区别, bash、dash与zsh shell, source、sh、bash、./执行脚本的区别

成功后再执行ls -l /bin/sh 看看

lrwxrwxrwx 1 root root 4 Feb 22 22:34 /bin/sh -> bash

修改过后,sh test.sh 就等价于 bash test.sh 或者 ./test.sh 了!

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

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}

dash: 不支持, 替代方法:采用expr或cut外部命令代替

8. 大小写转换

bash: 支持${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))或者外部命令做计算

14. $((expression))

bash: 支持id++,id–,++id,–id这样到表达式

dash: 不支持++,–, 替代方法:id+=1,id-=1, id=id+1,id=id-1

 

 

本文:Ubuntu:shell脚本运行异常, bash和dash的区别, sh和bash的区别, bash、dash与zsh shell, source、sh、bash、./执行脚本的区别