sh和Bash的区别

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

Bash和sh有什么区别?

在Bash和sh中编程时我们需要注意什么?

731002 次浏览

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

太长别读:Bash是sh的超集,具有更优雅的语法和更多的功能。几乎在所有情况下使用Bashsheband行都是安全的,因为它在现代平台上无处不在。

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

什么是sh?

sh(或Shell命令语言)是POSIX标准描述的一种编程语言。它有许多实现(ksh88Dash、…)。Bash也可以被认为是sh的实现(见下文)。

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

什么是Bash?

Bash最初是一个sh兼容的实现(尽管它比POSIX标准早了几年),但随着时间的推移,它已经获得了许多扩展。其中许多扩展可能会改变有效POSIX shell脚本的行为,因此Bash本身不是一个有效的POSIX shell。相反,它是POSIX外壳语言的方言。

Bash支持--posix开关,这使它更符合POSIX。如果作为sh调用,它还会尝试模仿POSIX。

sh=bash?

很长一段时间以来,在大多数GNU/Linux系统上,/bin/sh指向/bin/bash。因此,忽略两者之间的差异几乎变得安全了。但最近这种情况开始改变。

/bin/sh不指向/bin/bash的系统的一些流行示例(其中一些甚至可能不存在/bin/bash)是:

  1. 现代Debian和Ubuntu系统,默认将符号sh链接到dash
  2. Busybox,它通常在Linux系统启动时作为initramfs的一部分运行。它使用灰烬 shell实现。
  3. BSD系统,以及一般任何非Linux系统。OpenBSD使用pdkshKornShell的后代。FreeBSD的sh是原始Unix Bourne shell的后代。Solaris有自己的sh,很长一段时间不兼容POSIX;免费实现可从传家宝项目获得。

你怎么能找出/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选项,尽管GNU查找FreeBSD查找都支持它。

社邦线

最终,由您决定使用哪一个,将“sheband”行作为脚本的第一行。

例如。

#!/bin/sh

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

#!/bin/bash

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

#!/bin/dash

用哪一个

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

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

使用bash也有优点。它的特性使编程更方便,并且与其他现代编程语言的编程相似。这些包括作用域局部变量和数组等。Plainsh是一种非常简约的编程语言。

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

sh(Bourneshell)是一个shell命令行解释器,适用于Unix/类Unix操作系统。它提供了一些内置命令。在脚本语言中,我们将解释器表示为#!/bin/sh。它是其他shell最广泛支持的解释器,如bash(免费/开放)、kash(非免费)。

Bash是sh的超集。Bash支持sh。POSIX是一组定义符合POSIX的系统应该如何工作的标准。Bash实际上不是符合POSIX的shell。在脚本语言中,我们将解释器表示为#!/bin/bash

类比:

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

在此处输入图片描述

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

sh支持至少的特性POSIX要求(假设实现正确)。它也可能支持扩展。

bash,“Bourne再次Shell”,实现了sh和bash特定扩展所需的功能。完整的扩展集太长,无法在这里描述,并且随着新版本的发布而变化。差异记录在bash手册中。键入info bash并阅读“Bash功能”部分(当前版本的第6部分),或阅读当前在线留档

其他答案通常指出了Bash和POSIX shell标准之间的区别。然而,在编写可移植的shell脚本并习惯于Bash语法时,典型的bashism列表和相应的纯POSIX解决方案非常方便。这样的列表是在Ubuntu从Bash切换到Dash作为默认系统shell时编制的,可以在这里找到:https://wiki.ubuntu.com/DashAsBinSh

此外,有一个名为校验主义的很棒的工具可以检查脚本中的巴什主义,当您想确保脚本是可移植的时,它会派上用场。

文章UNIX.COM

Shell功能

下表列出了我认为会让你选择一个shell而不是另一个shell的大多数功能。它并不打算成为一个明确的列表,也不包括每个可能的shell的每一个可能的功能。一个功能只有在操作系统附带的版本中,或者如果它是直接从标准发行版编译的,才被认为是在shell中。特别是下面指定的C shell是SUNOS 4.*上可用的,相当多的供应商现在提供tcsh或他们自己的增强C shell(他们并不总是清楚地表明他们正在提供tcsh。

代码:

                                     sh   csh  ksh  bash tcsh zsh  rc   esJob control                          N    Y    Y    Y    Y    Y    N    NAliases                              N    Y    Y    Y    Y    Y    N    NShell functions                      Y(1) N    Y    Y    N    Y    Y    Y"Sensible" Input/Output redirection  Y    N    Y    Y    N    Y    Y    YDirectory stack                      N    Y    Y    Y    Y    Y    F    FCommand history                      N    Y    Y    Y    Y    Y    L    LCommand line editing                 N    N    Y    Y    Y    Y    L    LVi Command line editing              N    N    Y    Y    Y(3) Y    L    LEmacs Command line editing           N    N    Y    Y    Y    Y    L    LRebindable Command line editing      N    N    N    Y    Y    Y    L    LUser name look up                    N    Y    Y    Y    Y    Y    L    LLogin/Logout watching                N    N    N    N    Y    Y    F    FFilename completion                  N    Y(1) Y    Y    Y    Y    L    LUsername completion                  N    Y(2) Y    Y    Y    Y    L    LHostname completion                  N    Y(2) Y    Y    Y    Y    L    LHistory completion                   N    N    N    Y    Y    Y    L    LFully programmable Completion        N    N    N    N    Y    Y    N    NMh Mailbox completion                N    N    N    N(4) N(6) N(6) N    NCo Processes                         N    N    Y    N    N    Y    N    NBuiltin artithmetic evaluation       N    Y    Y    Y    Y    Y    N    NCan follow symbolic links invisibly  N    N    Y    Y    Y    Y    N    NPeriodic command execution           N    N    N    N    Y    Y    N    NCustom Prompt (easily)               N    N    Y    Y    Y    Y    Y    YSun Keyboard Hack                    N    N    N    N    N    Y    N    NSpelling Correction                  N    N    N    N    Y    Y    N    NProcess Substitution                 N    N    N    Y(2) N    Y    Y    YUnderlying Syntax                    sh   csh  sh   sh   csh  sh   rc   rcFreely Available                     N    N    N(5) Y    Y    Y    Y    YChecks Mailbox                       N    Y    Y    Y    Y    Y    F    FTty Sanity Checking                  N    N    N    N    Y    Y    N    NCan cope with large argument lists   Y    N    Y    Y    Y    Y    Y    YHas non-interactive startup file     N    Y    Y(7) Y(7) Y    Y    N    NHas non-login startup file           N    Y    Y(7) Y    Y    Y    N    NCan avoid user startup files         N    Y    N    Y    N    Y    Y    YCan specify startup file             N    N    Y    Y    N    N    N    NLow level command redefinition       N    N    N    N    N    N    N    YHas anonymous functions              N    N    N    N    N    N    Y    YList Variables                       N    Y    Y    N    Y    Y    Y    YFull signal trap handling            Y    N    Y    Y    N    Y    Y    YFile no clobber ability              N    Y    Y    Y    Y    Y    N    FLocal variables                      N    N    Y    Y    N    Y    Y    YLexically scoped variables           N    N    N    N    N    N    N    YExceptions                           N    N    N    N    N    N    N    Y

上表的关键字。

Y功能可以使用此shell完成。

shell中不存在N功能。

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

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

上表的说明

  1. 此功能不在原始版本中,但已成为几乎是标准的。
  2. 这个功能是相当新的,所以在许多人身上经常找不到版本的外壳,它正在逐渐进入标准分布。
  3. 这个shell的Vi模拟被许多人认为是不完整。
  4. 此功能不是标准的,但存在非官方的补丁执行此操作。
  5. 一个名为“pdksh”的版本是免费提供的,但没有AT&T版本的全部功能。
  6. 这可以通过shell可编程完成机制来完成。
  7. 只有通过ENV环境变量指定文件。

端子

  • 打开一个窗口的程序
  • xterm、rxvt、konsole、kvt、gnome终端、nxterm。

壳牌

  • 是在终端中运行的程序
  • Shell既是命令解释器又是编程语言
  • Shell只是一个执行命令的宏处理器。
  • 宏处理器是指扩展文本和符号以创建更大表达式的功能。

SH vs. BASH

SH

  • (壳)
  • 是一种特殊的外壳
  • 命令解释器和编程语言
  • BASH的前身

BASH

  • (伯恩-再次贝壳)
  • 是一种特殊的外壳
  • 命令解释器和编程语言
  • 具有sh功能等
  • SH的继任者
  • BASH是默认的shell

参考资料:

<强>壳gnu.org:

在它的底部,一个shell只是一个宏处理器执行术语宏处理器意味着文本和符号被扩展以创建更大的表达式。

Unix shell既是命令解释器又是编程语言。作为命令解释器,shell提供用户交互界面丰富的GNU实用程序集。编程语言功能允许要组合这些实用程序。包含命令的文件可以创建,并成为命令本身。这些新命令具有与目录中的系统命令(如 /bin)相同的状态,允许用户或组建立自定义环境以自动化他们的常见任务。

shell可以交互式或非交互式使用。在交互式模式,它们接受从键盘键入的输入。执行时非交互式,shell执行从文件读取的命令。

shell允许以同步和同步的方式执行GNU命令异步。shell等待同步命令完成在接受更多输入之前;异步命令继续执行与shell并行,同时读取和执行其他命令。重定向构造允许细粒度控制这些命令的输入和输出。此外,shell允许控制命令环境的内容。

Shell还提供了一组内置命令(内置命令)实现不可能或不方便通过以下方式获得的功能单独的实用程序例如,cd、出路、继续和exec不能在shell之外实现,因为它们直接操作贝壳本身。历史,getopts,杀死,或pwd内置,其中其他,可以在单独的实用程序中实现,但它们更多方便用作内置命令。所有shell内置都在随后的章节中描述。

虽然执行命令是必不可少的,但大多数功能(和复杂性)是由于它们的嵌入式编程语言。像任何高级语言一样,shell提供变量、流控制结构、引用和函数。

shell提供了专门用于交互式使用的功能,而不是而不是增强编程语言。这些交互式功能包括作业控制、命令行编辑、命令历史记录和别名。本手册中描述了这些功能中的每一个。

BASHgnu.org:

Bash是GNU的shell或命令语言解释器操作系统。这个名字是'Bourne-再次SHell'的首字母缩写,斯蒂芬伯恩的双关语,作者的直接祖先当前的Unix shell sh,出现在第七版贝尔实验室Unix的研究版本。

Bash与sh基本兼容,并包含有用的功能从Korn shell ksh和C shell csh。它旨在成为符合IEEE POSIX Shell和工具部分的实现IEEE POSIX规范(IEEE Standard 1003.1)。它提供对sh的功能改进,用于交互式和编程使用。

虽然GNU操作系统提供了其他shell,包括版本的csh,Bash是默认的shell。像其他GNU软件一样,Bash是非常可移植的。它目前运行在几乎所有版本的Unix和其他一些操作系统-独立支持的端口适用于MS-DOS、OS/2和Windows平台。

这个问题经常被提名为试图使用sh并惊讶于它的行为与bash不同的人的规范。以下是常见误解和陷阱的快速概述。

首先,你应该知道会发生什么。

  • 如果您使用sh scriptname运行脚本,或者使用scriptname运行脚本并在sheband行中有#!/bin/sh,您应该期待POSIXsh行为。
  • 如果你用bash scriptname运行你的脚本,或者用scriptname运行它,并有#!/bin/bash(或本地等效的)在sheang行,你应该期待Bash行为。

通常首选的解决方案是拥有正确的sheang并通过仅键入脚本名称(可能使用相对路径或完整路径)来运行脚本。除了正确的sheang之外,这还需要脚本文件具有执行权限(chmod a+x scriptname)。

那么,它们实际上是如何不同的呢?

Bash旨在向后兼容Bourne shell和POSIX,但有许多附加功能。Bash参考手册有一个试图列举差异的部分,但一些常见的混淆来源包括

  • [[sh中不可用(只有[更笨重和有限)。另见Bash中单方括号和双方括号的区别
  • sh没有数组。
  • 一些Bash关键字,如localsourcefunctionshoptletdeclareselect,不能移植到sh。(一些sh实现支持,例如local。)
  • Bash有许多C风格的语法扩展,如三参数for((i=0;i<=3;i++))循环,+=增量赋值等,$'string\nwith\tC\aescapes'功能暂时是接受POSIX(这意味着它现在可以在Bash中使用,但sh在仅遵守当前POSIX规范的系统上还不支持,并且可能在未来一段时间内不会支持)。
  • Bash支持<<<'here strings'
  • Bash有*.{png,jpg}{0..12}大括号扩展。
  • Bash已经扩展了全局化工具,例如**globstar)用于递归子目录,extglob用于使用不同的更通用的通配符语法。
  • #0仅在Bash中引用#1(更一般地说,#2指向#3的主目录)。这是在POSIX中,但可能在一些POSIX/bin/sh之前的实现中缺失。
  • Bash有<(cmd)>(cmd)的进程替换。
  • Bash有Csh风格的方便重定向别名,如2>&1 |&|> ... 2>&1&>
  • Bash支持<>重定向的协处理。
  • Bash具有一组丰富的扩展非标准参数扩展,例如${substring:1:2}${variable/pattern/replacement}、case转换等。
  • Bash对shell算术有显着扩展的功能(尽管仍然没有浮点支持)。有一个过时的遗留$[expression]语法,但是应该用POSIX算术$((expression))语法替换。(不过,一些遗留的POSIXsh之前的实现可能不支持。)
  • 一些内置命令具有不可移植的选项,例如type -aprintf -v和perennialecho -e
  • $RANDOM$SECONDS$PIPESTATUS[@]$FUNCNAME这样的魔术变量是Bash扩展。
  • Bash将一些系统设施公开为文件句柄,例如/dev/stdin/dev/fd/<number>/dev/tcp/<network address>
  • #0和[ "x" == "y" ]这样的语法差异是不可移植的([ ... ]中的#2应该与变量赋值分开,并且可移植字符串比较使用单个等于号)。
  • 许多许多仅Bash的扩展来启用或禁用可选行为并公开shell的内部状态。
  • 许多许多交互式使用的便利功能,但不影响脚本行为。

请记住,这是一个缩略列表。请参阅参考手册以获取完整的独家新闻,并为许多好的解决方法提供http://mywiki.wooledge.org/Bashism;和/或尝试http://shellcheck.net/,它警告许多仅Bash的功能。

一个常见的错误是有一个#!/bin/bash的sheband行,但仍然使用sh scriptname来实际运行脚本。这基本上禁用了任何仅限Bash的功能,所以你会遇到语法错误,例如尝试使用数组。(sheang行在语法上是一个注释,所以在这种情况下它会被忽略。)

不幸的是,当Bash被调用为sh时,当你尝试使用这些结构时,Bash不会发出警告。它也不会完全禁用所有只支持Bash的功能,所以通过调用它作为sh来运行Bash并不是检查脚本是否正确移植到#2/#3/POSIX#0sh0等变体的好方法。如果您想检查严格的POSIX合规性,请尝试#0在指定的POSIX模式(但似乎没有正确记录)。

顺便说一句,POSIX标准化工作旨在指定各种类似U*x的平台行为的行为,包括shellsh)。然而,这是一个不断发展的文档,因此,一些实现遵循POSIX规范的早期版本;此外,还有一些遗留的实现甚至没有尝试遵守POSIX。最初的Bourne shell有一些怪癖,后来被POSIX规范纠正,POSIX规范在很大程度上基于ksh88。(许多Bash扩展也是ksh的创新。)

Linux操作系统提供了不同类型的shell。虽然shell有许多共同的命令,但每种类型都有独特的功能。让我们研究一下不同类型的常用贝壳。

shshell:

Sh shell也称为Bourne shell。Sh shell是1977年AT&T贝尔实验室Stephen Bourne为Unix计算机开发的第一个shell。它包含许多脚本工具。

bash shell:

Bash shell代表Bourne再次Shell。Bash shell是大多数Linux发行版中的默认shell,并替代Sh shell(Sh shell也将在Bash shell中运行)。Bash shell可以无需修改即可执行绝大多数Sh shell脚本,并提供命令行编辑功能。

它们几乎相同,但#0具有更多功能-sh(或多或少)是bash的旧子集。

sh通常意味着最初的Bourne shell,它早于bashBourne *again* shell),创建于1977年。但是,在实践中,最好将其视为符合1992年POSIX标准的高度交叉兼容的shell。

#!/bin/sh开头或使用sh shell的脚本通常是为了向后兼容。任何unix/linux操作系统都有sh shell。在Ubuntush上经常调用dash,在MacOS上它是bash的特殊POSIX版本。这些shell可能是兼容标准行为、速度或向后兼容的首选。

bash比原来的sh更新,增加了更多的功能,并试图向后兼容shsh程序通常会在bash中运行良好。bash几乎在所有的linux/unix机器上都有,通常默认使用-除了MacOS默认为zsh的明显例外,从Catalina(10.15)开始。FreeBSD默认情况下没有安装bash

以最简单的方式解释差异:

有了基本的了解后,其他答案就更容易理解了。

壳牌-“Shell”是一个程序,它促进了用户和操作系统(内核)之间的交互。有许多可用的shell实现,如sh、Bashcshellz shell等。

使用任何shell程序,我们将能够执行该shell程序支持的命令。

Bash-它来源于Bourne-一个增益Shell。使用这个程序,我们将能够执行shell指定的所有命令。此外,我们将能够执行一些专门添加到这个程序中的命令。Bash与sh向后兼容。

Sh-它源自BourneShell。“sh”支持shell中指定的所有命令。这意味着,使用该程序,我们将能够执行Shell指定的所有命令。

有关更多信息,请参阅: