Bash 还是 KornShell (ksh)? [关闭]

Posted

技术标签:

【中文标题】Bash 还是 KornShell (ksh)? [关闭]【英文标题】:Bash or KornShell (ksh)? [closed] 【发布时间】:2010-09-09 15:28:32 【问题描述】:

我对 *nix 并不陌生,但最近我花了很多时间在提示符上。我的问题是使用 KornShell (ksh) 或 Bash Shell 有什么好处?使用其中一个的陷阱在哪里?

希望从用户的角度来理解,而不是纯粹的脚本。

【问题讨论】:

【参考方案1】:

我是一名 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 之间的分裂而过时,并且每个都引入了自己的不打印换行符(和其他行为)的约定。这个结果仍然可以在许多“配置”脚本中看到。

Ksh 对此采取了激进的方法 - 并引入了 print 命令,它实际上支持这两种方法(BSD 的 -n 选项和 SYSV 的尾随 \c 特殊字符)

但是,对于严肃的系统编程,我建议不要使用 shell,例如 python、perl。或者更进一步,使用像 puppet 这样的平台 - 它允许您通过良好的审计来观察和纠正整个系统集群的状态。

Shell 编程就像在未知水域中游泳,或者更糟。

使用任何语言进行编程都需要熟悉其语法、接口和行为。 Shell 编程也不例外。

【讨论】:

“交互式使用”是指手动提示到提示的命令执行,而不是运行捆绑此类命令的脚本? @foampile 是的,这就是“交互式使用”的意思。 回复:您的 read 差异,在非交互模式下,实际上可以为现代 bash 配置 - 请参阅 lastpipe 选项。 @CharlesDuffy 正确,当我写这篇文章时它是可用的 - 但是,它仍然不是默认行为 - 你需要 bash 4.2 或 4.3 和 lastpipe shopt。 Shopt 选项很尴尬,因为它们的设置实际上会触发语法错误。【参考方案2】:

Kornshell 和 Bash 之间的差异很小。两者相比有一定的优势,但差异很小:

BASH 更容易设置显示当前目录的提示。在 Kornshell 中做同样的事情是 hackish。 Kornshell 有关联数组,而 BASH 没有。现在,我最后一次使用关联数组是......让我想想......从来没有。 Kornshell 更好地处理循环语法。您通常可以在 Kornshell 循环中设置一个值,并在循环后使其可用。 Bash 以更简洁的方式处理从管道获取退出代码。 Kornshell 有print 命令,比echo 命令好很多。 Bash 有制表符补全。在旧版本中 Kornshell 有 r 历史命令,可让我快速重新运行旧命令。 Kornshell 的语法为cd old new,它将您目录和CD 中的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 人,因为我在 1990 年代学习了 Unix,而那是当时选择的 shell。我可以使用 Bash,但有时我会对此感到沮丧,因为习惯上我会使用 Kornshell 具有的一些小功能,而 BASH 没有而且它不起作用。因此,只要有可能,我都会将 Kornshell 设置为默认值。

但是,我要告诉你学习 BASH。 Bash 现在在大多数 Unix 系统和 Linux 上都实现了,而且有比 Kornshell 更多的资源可用于学习 BASH 和获得帮助。如果你需要在 BASH 中做一些奇特的事情,你可以在 *** 上发布你的问题,几分钟后你会得到十几个答案——其中一些甚至是正确的!

如果您有 Kornshell 问题并将其发布在 *** 上,您将不得不等待像我这样的资深黑客从午睡中醒来,然后才能得到答案。而且,如果那天他们在敬老院提供布丁,那就别再得到任何回应了。

BASH 现在只是首选的 shell,所以如果你必须学习一些东西,不妨选择流行的。

【讨论】:

为了完整起见,bash 版本 4 支持关联数组。我从来没有在任何一个 shell 中使用过 AA,所以我不能说它们是否比 Kornshell 的实现更好、更好或更差。 "您通常可以在 Kornshell 循环中设置一个值,并在循环后使其可用。" ——我觉得这很混乱。我当然支持变量应该只在其嵌套级别内而不是在它之外具有范围。 它与将命令传送到while readloop 有关。 Kornshell 在循环外访问变量没有问题。但是,对于 BASH,该管道是一个子进程,一旦循环完成,您就会失去价值。有办法解决这个问题。 @EarlGray 除非前面的命令是我的更改目录,否则这不起作用。其他人指出我可以这样做$ cd $PWD/foo/bar,但打字有点长。 在 bash 中,!vi 将运行以字母“vi”开头的最后一个运行命令。如果您不确定该命令是否是您想要的命令,请使用!vi:p,它将打印该命令并将其新添加到您的历史记录列表中,但不会实际运行它。然后,如果它 你想要的,一个简单的向上箭头输入,或者只是 !! 来运行它。查看man bash 并搜索HISTORY EXPANSION【参考方案3】:

在大多数 UNIX 系统中可用,ksh 符合标准、设计清晰、功能完善。 我认为书籍,ksh 中的帮助已经足够清晰,尤其是 O'Reilly 的书。 Bash 是一个群众。我只在家里将它作为 Linux 的 root 登录 shell。

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

【讨论】:

【参考方案4】:

Bash 是 Linux 的标准。 我的经验是 bash 比 ksh 或 csh 更容易找到帮助。

【讨论】:

我会说 basha 标准。 ;-) bash 只是 Linux 的标准。原始的 Bourne shell (sh) 是跨平台脚本的标准。 Posix-sh 是(或者可能“应该”)跨平台脚本的标准。 更正:Bash 是 Linux 的标准。 在 Debian 上,标准的 /bin/sh 实际上是破折号。【参考方案5】:

重击。

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

至少对于 bash,您可以确定它是一个单一的代码库,您只需要担心安装了什么(通常是最低)版本的 bash。在几乎所有现代(以及不太现代的)UNIX 上编写了大量脚本后,根据我的经验,对 bash 的编程更加可靠。

【讨论】:

如果你只做最小公分母 ksh,我同意。另一方面,正版 David Korn ksh93 在脚本编写方面具有引人注目的优势:速度接近 awk 进行文本处理;本机浮点数学;名称变量和关联数组,即使在未运行最新版本的系统上;等【参考方案6】:

对于脚本,我总是使用 ksh,因为它可以平滑 gotchas。

但我发现 bash 更适合交互式使用。对我来说,emacs 键绑定和制表符完成是主要的好处。但这主要是习惯的力量,而不是 ksh 的任何技术问题。

【讨论】:

“互动使用”是什么意思? @foampile:当您在终端命令行中键入内容时。 ;-) 我是这么认为的。谢谢【参考方案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 的数量,ksh 仍然是管理 HP-UX 的更好选择。 您可以在 bash 中使用 vi 补全和 set -o vi,并将其添加到您的 ~/.bashrc 文件中以使其持久化。这就是我的设置。【参考方案8】:

我的答案是“选择一个并学习如何使用它”。它们都是不错的贝壳​​; bash 可能有更多的花里胡哨,但它们都具有您想要的基本功能。如今,bash 更加普遍可用。如果你一直在使用 Linux,那就坚持下去吧。

如果您正在编程,尝试坚持简单的 'sh' 以实现可移植性是一种很好的做法,但是随着 bash 的普及,如今这些建议可能有点过时了。

了解如何使用完成和你的 shell 历史;偶尔阅读手册页并尝试学习一些新东西。

【讨论】:

在撰写此答案时,从编程的角度来看,ksh93 可以说有更多的花里胡哨(首先想到的是关联数组和名称变量)——尽管这在随后的八年中发生了变化。它仍然有浮点数学,而 bash 仍然缺乏。【参考方案9】:

我没有使用 ksh 的经验,但我使用过 bash 和 zsh。我更喜欢 zsh 而不是 bash,因为它支持非常强大的文件通配符、变量扩展修饰符和更快的制表符完成。

这里有一个简短的介绍:http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/

【讨论】:

【参考方案10】:

@foxxtrot

实际上,标准的 shell 是 Bourne shell (sh)。 Linux 上的 /bin/sh 实际上是 bash,但如果你的目标是跨平台脚本,你最好坚持使用原始 Bourne shell 的功能或将其编写为 perl 之类的东西。

【讨论】:

请注意,如果 /bin/sh (sym) 链接到 bash,则 bash 的行为会有所不同:如果使用名称 sh 调用 bash,它会尽可能地模仿 sh 的历史版本的启动行为尽可能,同时也符合 POSIX 标准。 在 Debian 上,标准 /bin/sh 实际上是 dash,debian almquist shell。当#!/bin/sh 拒绝他们的“有效” bash 命令时,这让很多人感到惊讶。【参考方案11】:

一方面,bash 具有制表符补全功能。仅这一点就足以让我更喜欢它而不是 ksh。

Z shell 将 ksh 的独特功能与 bash 提供的好东西很好地结合在一起,此外还有更多的东西。

【讨论】:

ksh 已完成,只是没有使用 tab 键。 ksh --version: "version sh (AT&T Research) 93t+ 2009-05-01" 有tab-completion和Esc-completion。 默认情况下,ksh 使用 作为补全,以防有人好奇。来源:kornshell.com/doc/faq.html【参考方案12】:

Bash 是基准,但这主要是因为您可以合理地确定它已安装在每个 *nix 上。如果您打算分发脚本,请使用 Bash。

很遗憾,我无法真正解决 shell 之间的实际编程差异。

【讨论】:

如果您计划分发脚本,请使用 posix-sh。 Bash 是一个很好的 shell,在 linux 上是默认的。较旧的 Unix 风格往往具有 sh、ksh 和 csh。在生产环境中,在所有系统上安装您选择的 shell 可能很难获得许可或宽恕。 我们在工作中使用的 AIX(美国主要金融机构)上默认没有安装它,我希望它是。 抱歉,Bash 不是“安装在每个 *nix 上”。尽管它可能在每个 GNU/Linux 发行版上都有。如果您支持 UNIX 或者您想遵循 POSIX,那么学习和使用 ksh,因为 ksh88(部分)是 sh 标准所基于的。如果您只使用 GNU/Linux 并且不关心与旧系统的兼容性,那么 Bash 就可以了。两者之间的大部分功能是可比的,但 Bash 让我很容易违反 POSIX。即使你明确告诉它不要这样做,它通常也会让你这样做。 Bash 中的 vi 模式也实现得很差。

以上是关于Bash 还是 KornShell (ksh)? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

安装KornShell(KSH)

KornShell (ksh) 环绕

如何在Ksh中把clear绑定到^L上?

korn vs bash 退出代码

我可以在 KornShell 中获取当前脚本的绝对路径吗?

.sh 和 .ksh —— 三种主要的 Shell简介(Korn shell)