sh和bash之间的区别

在编写shell程序时,我们经常使用/bin/sh/bin/bash 。 我通常使用bash ,但我不知道它们之间有什么区别。

bashsh之间的主要区别是什么?

bashsh编程时我们需要注意什么?

什么是sh

sh (或Shell命令语言)是POSIX标准描述的编程语言。 它有很多的实现( ksh88dash ,…)。 bash也可以被认为是sh一个实现(见下文)。

因为sh是一个规范,而不是一个实现,所以/bin/sh是在大多数POSIX系统上实际实现的符号链接(或硬链接)。

什么是bash

bash开始是一个sh兼容的实现(虽然它早于POSIX标准几年),但随着时间的推移,它已经获得了许多扩展。 这些扩展中的许多可能会改变有效的POSIX shell脚本的行为,所以bash本身并不是一个有效的POSIX shell。 相反,它是POSIX shell语言的一种方言。

bash支持一个--posix开关,这使得它更符合POSIX标准。 如果调用sh它也试图模仿POSIX。

sh = bash?

很长一段时间, /bin/sh用于在大多数GNU / Linux系统上指向/bin/bash 。 结果,忽略两者之间的差异几乎变得安全了。 但最近开始发生变化。

/bin/sh不指向/bin/bash (甚至有些/bin/bash甚至可能不存在)的一些stream行的系统示例如下:

  1. 现代Debian和Ubuntu系统,默认符号链接到dash ;
  2. Busybox ,通常在Linux系统启动时运行,作为initramfs一部分。 它使用ash壳实现。
  3. BSD和一般的非Linux系统。 OpenBSD使用pdksh ,它是Korn shell的后代。 FreeBSD的sh是原来的UNIX Bourne shell的后代。 Solaris有很长一段时间不符合POSIX标准; Heirloom项目提供免费的实施。

你怎么知道你的系统上有什么/bin/sh

复杂的是, /bin/sh可能是一个符号链接或硬链接。 如果这是一个符号链接,那么解决这个问题的便捷方式是:

 % file -h /bin/sh /bin/sh: symbolic link to bash 

如果这是一个硬链接,请尝试

 % find -L /bin -samefile /bin/sh /bin/sh /bin/bash 

实际上, -L标志涵盖了符号链接和硬链接,但是这种方法的缺点是不可移植 – POSIX 不需要 find来支持-samefile选项,尽pipeGNU find和FreeBSD都支持它。

Shebang线

最终,由你来决定使用哪一个,通过写“shebang”线。

例如

 #!/bin/sh 

将使用sh (以及发生的任何指向),

 #!/bin/bash 

如果可用,将使用/bin/bash如果不是,则会失败并显示错误消息)。 当然,你也可以指定另一个实现,例如

 #!/bin/dash 

哪一个使用

对于我自己的脚本,我更喜欢sh ,原因如下:

  • 它是标准化的
  • 这是更简单,更容易学习
  • 它可以跨POSIX系统移植 – 即使它们碰巧没有bash ,它们也必须有sh

使用bash也是有好处的。 其特点使得编程更加方便和类似于其他现代编程语言的编程。 这些包括像范围局部variables和数组。 Plain sh是一种非常简约的编程语言。

sh: http : //man.cx/sh bash: http : //man.cx/bash

TL; DR :bash是sh的一个超集,具有更优雅的语法和更多的function。 几乎在所有情况下使用bash shebang线是安全的,因为它在现代平台上非常普遍。

注意:在某些环境中,sh bash。 检查sh --version

从UNIX.COM发布

壳牌function

下表列出了我认为可以让您select一个shell的大部分function。 它并不打算成为一个明确的清单,并不包括每一个可能的shell的每一个可能的function。 只有在操作系统附带的版本中才会将function视为在shell程序中,或者如果直接从标准分发版编译的function是可用的。 特别是下面指定的C shell是在SUNOS 4上可用的。*相当数量的供应商现在可以运行tcsh或自己的增强型C shell(它们并不总是很明显地表明它们正在运行tcsh。

码:

  sh csh ksh bash tcsh zsh rc es Job control NYYYYYNN Aliases NYYYYYNN Shell functions Y(1) NYYNYYY "Sensible" Input/Output redirection YNYYNYYY Directory stack NYYYYYFF Command history NYYYYYLL Command line editing NNYYYYLL Vi Command line editing NNYYY(3) YLL Emacs Command line editing NNYYYYLL Rebindable Command line editing NNNYYYLL User name look up NYYYYYLL Login/Logout watching NNNNYYFF Filename completion NY(1) YYYYLL Username completion NY(2) YYYYLL Hostname completion NY(2) YYYYLL History completion NNNYYYLL Fully programmable Completion NNNNYYNN Mh Mailbox completion NNNN(4) N(6) N(6) NN Co Processes NNYNNYNN Builtin artithmetic evaluation NYYYYYNN Can follow symbolic links invisibly NNYYYYNN Periodic command execution NNNNYYNN Custom Prompt (easily) NNYYYYYY Sun Keyboard Hack NNNNNYNN Spelling Correction NNNNYYNN Process Substitution NNNY(2) NYYY Underlying Syntax sh csh sh sh csh sh rc rc Freely Available NNN(5) YYYYY Checks Mailbox NYYYYYFF Tty Sanity Checking NNNNYYNN Can cope with large argument lists YNYYYYYY Has non-interactive startup file NYY(7) Y(7) YYNN Has non-login startup file NYY(7) YYYNN Can avoid user startup files NYNYNYYY Can specify startup file NNYYNNNN Low level command redefinition NNNNNNNY Has anonymous functions NNNNNNYY List Variables NYYNYYYY Full signal trap handling YNYYNYYY File no clobber ability NYYYYYNF Local variables NNYYNYYY Lexically scoped variables NNNNNNNY Exceptions NNNNNNNY 

上面的表格的关键。

Yfunction可以使用这个shell来完成。

Nfunction在shell中不存在。

Ffunction只能通过使用shell函数机制来完成。

L readline库必须链接到shell才能启用此function。

上表的注释

 1. This feature was not in the original version, but has since become almost standard. 2. This feature is fairly new and so is often not found on many versions of the shell, it is gradually making its way into standard distribution. 3. The Vi emulation of this shell is thought by many to be incomplete. 4. This feature is not standard but unofficial patches exist to perform this. 5. A version called 'pdksh' is freely available, but does not have the full functionality of the AT&T version. 6. This can be done via the shells programmable completion mechanism. 7. Only by specifying a file via the ENV environment variable. 

终奌站

  • 程序(s)把窗户放好
  • xterm,rxvt,konsole,kvt,gnome-terminal,nxterm和eterm。

贝壳

  • 是在terminal运行的程序
  • Shell既是命令解释器又是编程语言
  • Shell只是一个执行命令的macros处理器。
  • macros处理器意味着文本和符号被扩展以创build更大的expression式的function。

SH VS. BASH

SH

  • (贝壳)
  • 是一个特定的shell
  • 一个命令解释器和一个编程语言
  • BASH的前身

BASH

  • (Bourne-Again SHell)
  • 是一个特定的shell
  • 一个命令解释器和一个编程语言
  • 有shfunction和更多
  • SH的继任者
  • BASH是默认的SHELL

参考资料:

SHELL gnu.org:

在它的基础上,一个shell只是一个执行命令的macros处理器 。 术语“ macros处理器”意味着扩展文本和符号以创build更大expression式的function。

Unix shell既是命令解释器又是编程语言。 作为一个命令解释器,shell提供了丰富的GNU实用程序的用户界面。 编程语言function允许将这些实用程序进行组合。 包含命令的文件可以被创build,并成为命令本身。 这些新命令与/ bin等目录中的系统命令具有相同的状态,允许用户或组build立自定义环境来自动执行其常见任务。

壳可以以交互方式或非交互方式使用。 在交互模式下,他们接受从键盘input的input。 当以非交互方式执行时,shell会执行从文件读取的命令。

一个shell允许同时和asynchronous执行GNU命令。 在接受更多的input之前,shell等待同步命令完成; asynchronous命令在读取并执行其他命令时继续与shell并行执行。 redirect构造允许对这些命令的input和输出进行细粒度的控制。 而且,shell允许控制命令环境的内容。

壳还提供一小组内置命令(内置),实现不可能或不方便通过单独的实用程序获取function例如,cd,break,continue和exec不能在shell之外实现,因为它们直接操作shell本身。 历史,getopts,kill或pwd内build等等可以在不同的工具中实现,但是作为内build命令使用起来更方便。 所有的内置shell都在后面的章节中介绍。

虽然执行命令是必不可less的, 但shell的大部分function(和复杂性)都是由于它们的embedded式编程语言。 像任何高级语言一样,shell提供variables,stream控制结构,引用和函数。

Shell提供了专门用于交互式使用的function,而不是增加编程语言。 这些交互function包括作业控制,命令行编辑,命令历史和别名。 本手册介绍了每个function。

BASH gnu.org:

Bash是GNU操作系统的shell或命令解释器。 这个名字是“Bourne-Again SHell”的缩写,是当前Unix shell sh的直接祖先的作者Stephen Bourne的一个双关语,出现在第七版的Bell Labs研究版本的Unix中。

Bash在很大程度上与sh兼容,并且集成了Korn shell ksh和C shell csh的有用特性。 它旨在成为IEEE POSIX规范(IEEE标准1003.1)的IEEE POSIX Shell和Tools部分的一致实现。 它提供了交互式和编程使用的shfunction改进。

虽然GNU操作系统提供了其他的shell,包括csh的一个版本,但Bash是默认的shell 。 像其他的GNU软件一样,Bash是非常便携的。 目前,它几乎可以运行在每一个版本的Unix和其他一些操作系统上 – 独立支持的MS-DOS,OS / 2和Windows平台。

这个问题经常被提名为试图使用sh人的规范,并且惊讶于它不像bash 。 这是一个常见的误解和陷阱的简要说明。

首先,你应该明白期望什么。

  • 如果使用sh scriptname运行脚本,或者使用scriptname运行脚本,并在shebang行中包含#!/bin/sh ,则应该使用POSIX sh行为。
  • 如果你用bash scriptname脚本名运行你的脚本,或者bash scriptname运行它,并且在shebang行中有#!/bin/bash (或者本地等价物),你应该期望Bash行为。

通过input正确的脚本并通过键入脚本名称(可能具有相对path或完整path)来运行脚本通常是首选解决scheme。 除了正确的shebang之外,这需要脚本文件具有执行权限( chmod a+x scriptname )。

那么,他们究竟有什么不同呢?

Bash参考手册有一个部分,试图列举的差异,但一些常见的混淆来源包括

  • [[sh是不可用的(只有[这是更笨重和有限的])。
  • sh没有数组。
  • 一些像localfunctionselect Bash关键字不能移植到sh
  • Bash有许多C风格的语法扩展,例如$'string\nwith\tC\aescapes'和三个参数for((i=0;i<=3;i++))循环, +=增量赋值等。
  • Bash支持<<<'here strings'
  • Bash有*.{png,jpg}{0..9}括号扩展。
  • ~仅在Bash中引用$HOME (更通用的~username~username的主目录)。
  • Bash有<(cmd)>(cmd)进程replace。
  • Bash支持使用<>redirect的coprocesses。
  • Bash大大扩展了shellalgorithm的function(尽pipe仍然没有浮点支持)和可变的子串操作。
  • 许多许多仅限Bash的扩展来启用或禁用可选行为并显示shell的内部状态。
  • 交互式使用的许多便利function,但不影响脚本行为。

请记住,这是一个删节列表。 请参阅全文的参考手册, http://mywiki.wooledge.org/Bashism有很多好的解决方法&#x3002; 和/或尝试http://shellcheck.net/警告许多Bashfunction&#x3002;

一个常见的错误是有一个#!/bin/bash shebang行,但是然后使用sh scriptname来实际运行脚本。 这基本上禁用任何Bashfunction,所以你会得到语法错误,例如尝试使用数组。

不幸的是,当Bash被调用为sh时,当你尝试使用这些构造时,Bash不会发出警告。 它并没有完全禁用所有 Bash-onlyfunction,所以通过调用它来运行Bash并不是一个很好的方法来检查脚本是否正确地移植到ash / dash / POSIX sh

其他答案一般指出了Bash和POSIX shell标准之间的区别。 但是,在编写可移植shell脚本并用于Bash语法时,典型的bashisms和相应的纯POSIX解决scheme的列表非常方便。 当Ubuntu从Bash切换到Dash作为默认的系统shell时,这样的列表已经被编译,可以在这里find: https : //wiki.ubuntu.com/DashAsBinSh

此外,还有一个叫做checkbashisms的工具,可以检查脚本中的bashisms,当你想确保你的脚本是可移植的时候,它会很方便。

Shell是用户和操作系统之间的接口,用于访问操作系统的服务。 它可以是GUI或CLI(命令行界面)。

sh (Bourne sh el)是一个shell命令行解释器,用于Unix / Unix类操作系统。 它提供了一些内置的命令。 在脚本语言中,我们将解释器表示为#!/bin/sh 。 它是其他shell如bash(free / open),kash(不是free)所支持的。

BashB ourne a gain s hell)是Bourne shell的shell替代品。 Bash是sh的超集。 Bash支持sh。 POSIX是一套定义POSIX兼容系统应该如何工作的标准。 Bash实际上并不是POSIX兼容的shell。 在脚本语言中,我们将解释器表示为#!/bin/bash

比喻:

  • Shell就像一个接口或规范或API。
  • sh是一个实现Shell接口的类。
  • Bash是sh的一个子类。

/bin/sh可能会或可能不会调用与/bin/bash相同的程序。

sh 至less支持POSIX所要求的特性(假设一个正确的实现)。 它也可以支持扩展。

bash ,“Bourne Again Shell”,实现了sh和bash特定扩展所需的function。 全套扩展在这里描述的时间太长,并且随着新版本的不同而不同。 差异logging在bash手册中。 inputinfo bash并阅读“Bashfunction”部分(当前版本的第6部分),或者在线阅读当前文档 。