【发布时间】:2010-09-09 15:28:32
【问题描述】:
我对 *nix 并不陌生,但最近我花了很多时间在提示符上。我的问题是使用 KornShell (ksh) 或 Bash Shell 有什么好处?使用其中一个的陷阱在哪里?
希望从用户的角度来理解,而不是纯粹的脚本。
【问题讨论】:
标签: bash shell unix scripting ksh
我对 *nix 并不陌生,但最近我花了很多时间在提示符上。我的问题是使用 KornShell (ksh) 或 Bash Shell 有什么好处?使用其中一个的陷阱在哪里?
希望从用户的角度来理解,而不是纯粹的脚本。
【问题讨论】:
标签: bash shell unix scripting ksh
我是一名 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 编程也不例外。
【讨论】:
read 差异,在非交互模式下,实际上可以为现代 bash 配置 - 请参阅 lastpipe 选项。
Kornshell 和 Bash 之间的差异很小。两者相比有一定的优势,但差异很小:
print 命令,比echo 命令好很多。r 历史命令,可让我快速重新运行旧命令。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 中做一些奇特的事情,你可以在 Stackoverflow 上发布你的问题,几分钟后你会得到十几个答案——其中一些甚至是正确的!
如果您有 Kornshell 问题并将其发布在 Stackoverflow 上,您将不得不等待像我这样的资深黑客从午睡中醒来,然后才能得到答案。而且,如果那天他们在敬老院提供布丁,那就别再得到任何回应了。
BASH 现在只是首选的 shell,所以如果你必须学习一些东西,不妨选择流行的。
【讨论】:
while readloop 有关。 Kornshell 在循环外访问变量没有问题。但是,对于 BASH,该管道是一个子进程,一旦循环完成,您就会失去价值。有办法解决这个问题。
$ cd ${PWD/foo/bar},但打字有点长。
!vi 将运行以字母“vi”开头的最后一个运行命令。如果您不确定该命令是否是您想要的命令,请使用!vi:p,它将打印该命令并将其新添加到您的历史记录列表中,但不会实际运行它。然后,如果它 是 你想要的,一个简单的向上箭头输入,或者只是 !! 来运行它。查看man bash 并搜索HISTORY EXPANSION。
在大多数 UNIX 系统中可用,ksh 符合标准、设计清晰、功能完善。 我认为书籍,ksh 中的帮助已经足够清晰,尤其是 O'Reilly 的书。 Bash 是一个群众。我只在家里将它作为 Linux 的 root 登录 shell。
对于交互式使用,我更喜欢 Linux/UNIX 上的 zsh。我在 zsh 中运行脚本,但我会在 AIX ksh 中测试我的大部分脚本和函数。
【讨论】:
Bash 是 Linux 的标准。
我的经验是 bash 比 ksh 或 csh 更容易找到帮助。
【讨论】:
重击。
各种 UNIX 和 Linux 实现具有各种不同的 ksh 源代码级别实现,其中一些是真正的 ksh,其中一些是 pdksh 实现,其中一些只是指向具有“ksh”特性的其他一些 shell 的符号链接。这可能会导致执行行为出现奇怪的差异。
至少对于 bash,您可以确定它是一个单一的代码库,您只需要担心安装了什么(通常是最低)版本的 bash。在几乎所有现代(以及不太现代的)UNIX 上编写了大量脚本后,根据我的经验,对 bash 的编程更加可靠。
【讨论】:
awk 进行文本处理;本机浮点数学;名称变量和关联数组,即使在未运行最新版本的系统上;等
对于脚本,我总是使用 ksh,因为它可以平滑 gotchas。
但我发现 bash 更适合交互式使用。对我来说,emacs 键绑定和制表符完成是主要的好处。但这主要是习惯的力量,而不是 ksh 的任何技术问题。
【讨论】:
这是一场 Unix 与 Linux 的战斗。大多数(如果不是全部)Linux 发行版都安装了 bash 并且 ksh 是可选的。大多数 Unix 系统,如 Solaris、AIX 和 HPUX,都默认使用 ksh。
就我个人而言,我总是使用 ksh,我喜欢 vi 补全,而且我几乎所有事情都使用 Solaris。
【讨论】:
set -o vi,并将其添加到您的 ~/.bashrc 文件中以使其持久化。这就是我的设置。
我的答案是“选择一个并学习如何使用它”。它们都是不错的贝壳; bash 可能有更多的花里胡哨,但它们都具有您想要的基本功能。如今,bash 更加普遍可用。如果你一直在使用 Linux,那就坚持下去吧。
如果您正在编程,尝试坚持简单的 'sh' 以实现可移植性是一种很好的做法,但是随着 bash 的普及,如今这些建议可能有点过时了。
了解如何使用完成和你的 shell 历史;偶尔阅读手册页并尝试学习一些新东西。
【讨论】:
我没有使用 ksh 的经验,但我使用过 bash 和 zsh。我更喜欢 zsh 而不是 bash,因为它支持非常强大的文件通配符、变量扩展修饰符和更快的制表符完成。
这里有一个简短的介绍:http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/
【讨论】:
@foxxtrot
实际上,标准的 shell 是 Bourne shell (sh)。 Linux 上的 /bin/sh 实际上是 bash,但如果你的目标是跨平台脚本,你最好坚持使用原始 Bourne shell 的功能或将其编写为 perl 之类的东西。
【讨论】:
/bin/sh 实际上是 dash,debian almquist shell。当#!/bin/sh 拒绝他们的“有效” bash 命令时,这让很多人感到惊讶。
一方面,bash 具有制表符补全功能。仅这一点就足以让我更喜欢它而不是 ksh。
Z shell 将 ksh 的独特功能与 bash 提供的好东西很好地结合在一起,此外还有更多的东西。
【讨论】:
ksh --version: "version sh (AT&T Research) 93t+ 2009-05-01" 有tab-completion和Esc-completion。
Bash 是基准,但这主要是因为您可以合理地确定它已安装在每个 *nix 上。如果您打算分发脚本,请使用 Bash。
很遗憾,我无法真正解决 shell 之间的实际编程差异。
【讨论】: