我能想到几个不同之处;我只是想在这里,没有特别的顺序:
Python&;公司的设计宗旨是擅长编写脚本.Bash&;Co.被设计成only个擅长脚本编写的公司,绝对不会妥协.IOW:Python被设计成擅长脚本和非脚本,Bash只关心脚本.
Bash&;Co.是非类型化的,Python&;Co.是强类型化的,这意味着数字123
、字符串123
和文件123
有很大的不同.但是,它们不是statically类型的,这意味着它们需要具有不同的文字,以便将它们分开.
示例:
| Ruby | Bash
-----------------------------------------
number | 123 | 123
string | '123' | 123
regexp | /123/ | 123
file | File.open('123') | 123
file descriptor | IO.open('123') | 123
URI | URI.parse('123') | 123
command | `123` | 123
Python&;Bash&;公司的设计规模为down至down02个项目.
在Bash&;文件、目录、文件描述符、进程都是一级对象,在Python中,只有Python对象是一级对象,如果要操作文件、目录等,必须首先将它们包装在Python对象中.
Shell编程基本上是数据流编程.没有人意识到这一点,即使是编写Shell的人,但事实证明Shell非常擅长这一点,而通用语言则不太擅长.在通用编程世界中,数据流似乎主要被视为并发模型,而不是编程范式.
我有一种感觉,试图通过将特性或DSL绑定到通用编程语言来解决这些问题是行不通的.至少,我还没有看到它令人信服的实施.有RuSH(Ruby Shell),它试图用Ruby实现shell,还有rush,它是Ruby中shell编程的内部DSL,还有Hotwire,它是一个Python shell,但我认为这些都无法与Bash、Zsh、Fish和Friends竞争.
事实上,IMHO,目前最好的shell是Microsoft PowerShell,这是非常令人惊讶的,考虑到现在有decades个,微软一直有worst个shell evar个.我是说,COMMAND.COM
?真正地(不幸的是,他们仍然有一个蹩脚的终端.它仍然是"命令提示符",自从什么?Windows 3.0?)
PowerShell基本上是通过忽略微软曾经做过的一切(COMMAND.COM
、CMD.EXE
、VBScript、JScript)而创建的,而是从Unix shell开始,然后移除所有向后兼容性的障碍(比如命令替换的反勾号),并稍微调整一下,使其对Windows更友好(比如使用现在未使用的反勾号作为转义字符,而不是反斜杠,它是Windows中的路径组件分隔符).在那之后,就是魔法发生的时候.
与Python相比,它们基本上做出了相反的 Select ,从而解决了上面的problem 1 and 3个问题.Python首先关心大型程序,其次是脚本.Bash只关心脚本编写.PowerShell首先关心脚本编写,其次是大型程序.对我来说,一个决定性的时刻是观看杰弗里·斯诺弗(Jeffrey Snover,PowerShell的首席设计师)的采访视频,采访者问他用PowerShell可以编写多大的程序,斯诺弗毫不犹豫地回答:"80个字符."当时我意识到,这是一个在微软"得到"shell编程的人(可能与PowerShell是由微软的编程语言组(即lambda演算数学书呆子)或操作系统组(内核书呆子)开发的,而不是服务器组(即实际上是use个shell的系统管理员)有关),我应该认真看看PowerShell.
Number 2通过静态键入参数来解决.因此,您可以只编写123
,并且PowerShell知道它是字符串、数字还是文件,因为cmdlet(这是PowerShell中调用的Shell命令)向Shell声明其参数的类型.这有相当深的影响:与Unix不同,在Unix中,每个命令负责解析自己的参数(Shell基本上将参数作为字符串数组传递),而PowerShell中的参数解析是由shell完成的.cmdlet指定它们的所有选项、标志和参数,以及它们的类型、名称和文档(!)到shell,然后shell可以在一个集中的位置执行参数解析、制表符完成、智能感知、内联文档弹出窗口等.(这并不是革命性的,PowerShell设计者承认像数字命令语言(DCL)和IBM OS/400命令语言(CL)这样的shell是现有技术.对于任何使用过AS/400的人来说,这听起来应该很熟悉.在OS/400中,您可以编写一个shell命令,如果您不知道某些参数的语法,您可以简单地省略它们,然后按F4,这将带来一个菜单(类似于HTML表单),其中包含带标签的字段、下拉列表、帮助文本等.只有在操作系统知道所有可能的参数及其类型的情况下,这才是可能的.)在Unix shell中,此信息通常重复三次:在命令本身的参数解析代码中、在用于制表符完成的bash-completion
脚本中和在手册页中.
由于PowerShell对强类型对象(包括文件、进程、文件夹等)进行操作,因此解决了Number 4问题.
Number 5特别有趣,因为PowerShell是我所知道的唯一的shell,在那里编写它的人实际上是aware的事实,即shell本质上是数据流引擎,并故意将其实现为数据流引擎.
Another nice thing about PowerShell are the naming conventions: all cmdlets are named Action-Object
and moreover, there are also standardized names for specific actions and specific objects. (Again, this should sound familar to OS/400 users.) For example, everything which is related to receiving some information is called Get-Foo
. And everything operating on (sub-)objects is called Bar-ChildItem
. So, the equivalent to ls
is Get-ChildItem
(although PowerShell also provides builtin aliases ls
and dir
– in fact, whenever it makes sense, they provide both Unix and CMD.EXE
aliases as well as abbreviations (gci
in this case)).
但是killer featureIMO是强类型的对象管道.虽然PowerShell派生自Unix shell,但有一个非常重要的区别:在Unix中,所有通信(通过管道、重定向以及命令参数)都是使用无类型、非 struct 化字符串完成的.在PowerShell中,它都是强类型的 struct 化对象.这是如此令人难以置信的强大,我真的很奇怪为什么其他人都没有想到它.(嗯,它们已经流行了,但它们从未变得流行起来.)在我的shell脚本中,我估计多达三分之一的命令只是充当另外两个不同意通用文本格式的命令之间的适配器.PowerShell中的许多适配器都消失了,因为cmdlet交换 struct 化对象而不是非 struct 化文本.如果你看一下inside个命令,那么它们基本上由三个阶段组成:将文本输入解析为内部对象表示,操作对象,将它们转换回文本.同样,第一阶段和第三阶段基本上消失了,因为数据已经作为对象传入.
然而,设计师们非常小心地通过他们所谓的Adaptive Type System来保持shell脚本的动态性和灵活性.
不管怎样,我不想把这变成一个PowerShell广告.PowerShell有很多很棒的地方,尽管大多数都与Windows或特定的实现有关,而与概念无关.(例如,它是在.NET中实现的这一事实意味着,如果.NET framework由于其他一些需要它的应用程序而不在文件系统缓存中,那么您第一次启动shell可能需要几秒钟的时间.考虑到您经常在不到一秒钟的时间内使用shell,这是完全不可接受的.)
我想说的最重要的一点是,如果你想看看脚本语言和shell的现有工作,you shouldn't stop at Unix and the Ruby/Python/Perl/PHP family.例如,已经提到了Tcl.Rexx将是另一种脚本语言.Emacs Lisp将是另一个.在shell领域,有一些已经提到的大型机/中端shell,比如OS/400命令行和DCL.还有Plan9的rc.