Bash 还是 KornShell(ksh)?

72

我不是*nix的新手,但最近我花了很多时间在命令提示符下。我的问题是使用KornShell(ksh)或Bash Shell有什么优势?其中一个与另一个相比有什么缺点?

我想从用户的角度来理解,而不仅仅是脚本编写。

12个回答

141

Kornshell和Bash之间的差别很小。它们各自有一些优势,但是差异非常微小:

  • BASH更容易设置一个显示当前目录的提示符。在Kornshell中做同样的事情则比较棘手。
  • Kornshell具有关联数组而BASH没有。不过,我上次使用关联数组是什么时候呢...让我想想...从来没有。
  • Kornshell处理循环语法稍微好一些。在Kornshell循环中通常可以设置一个值,并且在循环后这个值仍然可用。
  • Bash以更清晰的方式从管道获取退出代码。
  • Kornshell具有print命令,该命令比echo命令更好。
  • Bash具有标签完成功能。在旧版本中
  • Kornshell具有r历史命令,允许我快速重新运行以前的命令。
  • Kornshell具有语法cd old new,它将old替换为new并切换到那里。当你在一个名为/foo/bar/barfoo/one/bar/bar/foo/bar的目录中,并需要CD到/foo/bar/barfoo/two/bar/bar/foo/bar时,这非常方便。在Kornshell中,你只需要简单地执行cd one two就可以了。在BASH中,你必须执行cd ../../../../../two/bar/bar/foo/bar

我是个老的Kornshell用户,因为我在20世纪90年代学习Unix并使用这种Shell。我也可以使用Bash,但有时候会因为我习惯使用Kornshell拥有但BASH没有的一些小功能而感到沮丧。所以,只要可能,我就将Kornshell设置为我的默认Shell。

然而,我建议你学习BASH。在大多数Unix系统和Linux上都已经实现了BASH,并且有更多的资源可用于学习BASH和获取帮助,相对于Kornshell而言。如果你需要在BASH中完成一些奇特的事情,你可以去Stackoverflow发布问题,几分钟内就能得到十几个答案,其中一些甚至是正确的。

如果你有一个Kornshell的问题并在Stackoverflow上发布它,你必须等待某个老年人像我一样从午睡中醒来才能得到答案。如果当天老人院里提供布丁,那么别指望能得到任何回应。

BASH现在是首选的shell,如果你必须学习的话,最好选择流行的东西。


8
为了完整起见,Bash版本4支持关联数组。我从未在任何shell中使用过AAs,所以无法确定它们的工作效果是更好、更差还是与Kornshell的实现相同。 - chepner
4
通常在Kornshell循环中设置一个值后,可以在循环结束后仍然使用该值。但这句话让我感到非常困惑。我当然赞成变量应该只在其嵌套级别内部具有作用域,而不应该超出其范围。 - amphibient
3
这与通过管道将命令传输到“while read”循环有关。Kornshell在循环外部访问变量没有问题。但是,在BASH中,该管道是一个子进程,并且一旦循环完成,您将失去该值。有方法可以解决这个问题。 - David W.
3
@EarlGray,除非之前的命令是更改目录,否则这不起作用。有人指出我可以使用 $ cd ${PWD/foo/bar},但这有点长,不太方便输入。 - David W.
6
在bash中,!vi将执行以字母'vi'开头的最后一个运行命令。如果您不确定该命令是否是您想要的,请使用!vi:p打印出该命令并将其添加到您的历史记录列表中,但不会实际运行它。然后,如果它确实是您想要的,只需按上箭头回车或者直接使用!!来运行它即可。请参阅man bash并搜索HISTORY EXPANSION - Wildcard
显示剩余11条评论

48

Bash。

不同的UNIX和Linux实现有各种不同的ksh源级别实现,其中一些是真正的ksh,一些是pdksh实现,还有一些只是指向具有“ksh”性格的其他shell的符号链接。 这可能会导致执行行为上的奇怪差异。

至少使用bash,您可以确信它是单一代码库,您所担心的就是安装了什么(通常是最低)版本的bash。在几乎所有现代(和不太现代)的UNIX上进行大量脚本编程后,根据我的经验,使用bash进行编程更加可靠和一致。


4
如果你只是使用最基础的ksh,我同意。然而真正的David Korn ksh93在脚本编写方面有着强大的优势:速度接近于awk用于文本处理;原生支持浮点数运算;namevars和关联数组即使在不运行最新版本的系统上也可以使用等等。 - Charles Duffy

35

我是一名Korn Shell老手,所以我的观点都基于这个角度。

但是,我也熟悉Bourne shell、ksh88和ksh93,并且大多数情况下我知道哪些功能在哪个壳中受支持。(我应该跳过ksh88,因为它已经不再广泛分发了。)

对于交互式使用,请根据您的需要选择合适的内容。尝试一下。我喜欢能够同时用同一个shell进行交互和编程。

我从SVR2上的ksh88转到tcsh,再到ksh88sun(增加了重要的国际化支持)和ksh93。我尝试了bash,因为它扁平化了我的历史记录而讨厌它。然后我发现了shopt -s lithist,一切都很好。 (lithist选项确保在命令历史记录中保留换行符。)

对于shell编程,如果您想要一个一致的编程语言、良好的POSIX兼容性和良好的性能,则强烈推荐使用ksh93,因为许多常见unix命令可以作为内置函数可用。

如果您想要可移植性,请至少使用两者。并确保您拥有良好的测试套件。

不同shell之间存在许多微妙的差异。例如考虑从管道中读取:

b=42 && echo one two three four |
    read a b junk && echo $b
这会在不同的shell中产生不同的结果。Korn-shell从后往前运行管道,管道中的最后一个元素在当前进程中运行。Bash直到v4.x才支持这种有用的行为,即使如此,它也不是默认行为。
另一个例子说明一致性:echo命令本身已经过时了,因为BSD和SYSV unix之间的分裂,它们各自引入了自己的约定来控制不打印换行符(和其他行为)。这导致在许多“configure”脚本中仍然可以看到这种情况。
Ksh采取了一种激进的方法——引入了print命令,实际上支持两种方法(来自BSD的-n选项和来自SYSV的尾随\c特殊字符)。
然而,对于严肃的系统编程,我建议使用像Python、Perl这样的Shell以外的语言。或者更进一步,使用像puppet这样的平台,它允许您观察和纠正整个系统集群的状态,并拥有良好的审计功能。
Shell编程就像在未知的水域中游泳,甚至更糟。
在任何语言中编程都需要熟悉其语法、接口和行为。Shell编程并没有什么不同。

“交互使用”是指手动提示到提示的命令执行,而不是运行捆绑这些命令的脚本吗? - amphibient
3
@foampile 是的,这就是“交互使用”的意思。 - Telemachus
2
关于您的“read”差异,对于现代bash来说,在非交互模式下实际上是可配置的--请参阅lastpipe选项。 - Charles Duffy
@CharlesDuffy 正确,而且当我写这篇文章时它是可用的 - 但是,它仍然不是默认行为 - 您需要 bash 4.2 或 4.3 和 lastpipe shopt。Shopt选项很棘手,因为它们的设置实际上可能会触发语法错误。 - Henk Langeveld

7

这是一场Unix与Linux之间的争论。大多数Linux发行版都已安装了bash,而ksh则是可选的。而大多数Unix系统(如Solaris、AIX和HPUX)则默认使用ksh。

个人而言,我总是使用ksh,我喜欢vi自动补全功能,并且几乎将Solaris用于所有事情。


HP-UX提供sh、csh和ksh作为默认的shell。在11.31版本中,默认安装介质中包含了bash。但是考虑到全球仍有很多使用10.20版本的情况,对于管理HP-UX来说,ksh仍然是更好的选择。 - Stan Graves
你可以在bash中使用vi完成功能,方法是使用set -o vi命令,并将其添加到你的~/.bashrc文件中以使其持久化。这就是我自己的设置方式。 - Wildcard

6

对于脚本,我总是使用ksh,因为它可以平滑处理一些问题

但是我发现对于交互式使用,bash更加舒适。对我来说,emacs键绑定和标签自动完成是主要的优点。但这主要是习惯力量,而不是ksh的任何技术问题。


“交互使用”是什么意思? - amphibient
1
当你在输入终端命令行时。;-) - Jon Ericson
1
我也是这么想的。谢谢。 - amphibient

5

4

首先,Bash具有Tab键自动补全功能。仅凭这一点就足以使我更喜欢Bash而非Ksh。

Z shell很好地结合了Ksh的独特特性和Bash提供的优点,还有更多的功能。


3
Ksh有自动补全功能,只是不能用Tab键触发。 - user13158
2
ksh --version: "version sh (AT&T Research) 93t+ 2009-05-01" 具有制表符自动补全和 Esc 自动补全功能。 - Dennis Williamson
4
默认情况下,ksh使用<ESC><ESC>作为补全命令,如果有人感兴趣的话。来源:http://kornshell.com/doc/faq.html - Katerberg

3

@foxxtrot

实际上,标准的shell是Bourne shell(sh)。在Linux上,/bin/sh实际上是bash,但如果你想编写跨平台脚本,最好坚持使用原始Bourne shell的功能或者使用像perl这样的语言编写脚本。


请注意,如果/bin/sh符号链接到bash,则bash的行为会有所不同:如果使用名称sh调用bash,则它会尽可能地模仿历史版本的sh的启动行为,同时也符合POSIX标准。 - glenn jackman
4
在Debian中,标准的/bin/sh实际上是dash,即Debian Almquist shell。当人们使用“有效”的bash命令被#!/bin/sh拒绝时,这会让很多人感到惊讶。 - thom

3
我的答案是“选择一个并学会如何使用它”。它们都是不错的shell;bash可能有更多的功能,但它们都有你需要的基本功能。现在,bash更加普遍可用。如果你一直在使用Linux,就坚持使用它吧。
如果你正在编程,尽量保持对可移植性的支持,只使用纯粹的“sh”是个好习惯,但由于现在广泛使用bash,这条建议可能有点过时了。
学习如何使用补全和shell历史记录;偶尔阅读手册并尝试学习一些新知识。

1
截至本答案撰写时,从编程角度来看,ksh93可以说拥有更多的功能(关联数组和名称变量首先想到) - 尽管在这八年中发生了变化。它仍然具有浮点数运算,而bash仍然缺乏此功能。 - Charles Duffy

2

大多数UNIX系统都提供ksh,它符合标准、设计清晰、功能全面。我认为关于ksh的书籍和帮助已经足够清晰明了,特别是O'Reilly出版的书籍。

Bash很臃肿。我只在家里的Linux系统中将其作为root登录shell。

对于交互式使用,我更喜欢在Linux/UNIX上使用zsh。我会在zsh中运行脚本,但我会在AIX ksh中测试大部分脚本和函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接