首頁  >  文章  >  後端開發  >  为什么 Python(或 Ruby、Perl 等)没有取代 Bash 成为系统 Shell?

为什么 Python(或 Ruby、Perl 等)没有取代 Bash 成为系统 Shell?

WBOY
WBOY原創
2016-06-06 16:22:571858瀏覽

关联问题:zhihu.com/question/2024

如果编程语言是否可以作为系统Shell使用,与它的流行程度正相关,那为何Python还没有成为标配的系统Shell?
选择Python(或其它)作为系统Shell,一定就比Bash或者POSIX Shell更经济吗?

回复内容:

Shell 是有很多缺(tuo)陷(xie)的。比如说一个最简单的例子,如果你下载的文件名字里面有很多空格,在准备批量操作比如归档的时候都会很麻烦。Shell 的自动解析通常会把你搞得很惨。而且那东西还是个feature 对吧?那不是bug。

其实这就是很典型的不适合用Shell去解的问题嘛。你找个没有自动解析的工具,比如说随便哪种脚本语言都行啦。为什么选Ruby呢?当然因为Ruby有 irb 咯。

irb(main):033:0> dir = 'Archive-Dir'
irb(main):034:0> dst = 'Your-destination-directory'
irb(main):035:0> num = 16
irb(main):036:0> lines = `ls -rt ~/Downloads/ | tail -n #{num}`.split("\n")
irb(main):037:0> lines.each { |l| print `mv "#{l}" #{dir}/#{dst}` }

这样一来就是这么简单了,其实就只有两行嘛。我只所以写那么多变量是因为我还有很多文件需要交互的去做的。那么我就只需要改变量,然后用箭头找历史,一路回车就行了。

但是为什么 Shell 还是不能够被取代呢?因为还有大量的交互式任务用 Shell 的时候可以简单到不可想象的地步。

diff -u awk -F '/' '{print $NF}' | sort ) 2>&1 | \
egrep '^\+[^+]' |sed -e 's/^\+//' | \
xargs -n 1 ./download.sh

甚至于是这样

diff -u awk -F '/' '{print $NF}' | sort ) 2>&1 | \
egrep '^\+[^+]' |sed -e 's/^\+//' | \
xargs -n 1 ./download.sh

所以呢,应该用 Shell 处理的问题还是要用 Shell 处理的。

顺便问一下,为什么不用 Python ?

我真的不想仅仅因为没对齐…… …… ……

人生苦短,不用Python。


稍微补充一点 Shell 的好处。就是 Shell 这样的东西呢,毕竟也算是历史悠久,酒精考验的老同志了,所以不容易出现用户还得自己分辨不同版本下面数学计算究竟应该等于多少这样的事情。。。

为什么 Python(或 Ruby、Perl 等)没有取代 Bash 成为系统 Shell? @狼大人 和 @yegle 说的都很有道理,不过我觉得大家都忽视了一点,就是一个软件的惯性(或者说是一种习惯)。尤其是 Shell 这种基础设施的软件,一旦启用了一会,很多人很多软件就会采用这样的标准,所以只要不是太差一般就不会改变。

举一个例子吧,我的老师教我使用 Linux 的时候,编辑文件是用 vi,所以后来有很长一段时间我都不知道 vim 是什么东西。后来我也一直使用 vi 这个命令,倒不是什么少一个字母比较方便的问题,就是习惯了。我们也都知道在 Linux 中是没有 vi 的,至少 debian 是没有的,默认安装了 vim-tiny,然后可以安装完整版的 vim,vi 则一直是 vim 的一个 link。我不知道是我的老师开始的时候用 UNIX 习惯使用 vi,还是我老师的老师是用 UNIX 的然后教他的时候就教了 vi,反正作为从 UNIX 继承过来的一套软件,命令的格式、样式也算是一种惯性,不会也不应该轻易的改变。Linux 中还有很多这样的例子,比如 cc -> gcc,lex -> flex,yacc -> bison,都是遵循 UNIX 的习惯。

也许是类 UNIX 系统中,有太多太多的脚本是使用 Shell 脚本写的,所以这个不应该轻易的改变。比如,如果我们自己编译过一些软件或者类库,我们一定会对 ./configure 这个文件不会陌生,这个就是一个用 Shell 写(准确的应该说是生成的)的脚本。打开这个文件的第一行,你会看到 #! /bin/sh 这样的一段。我们都知道 sh 和 bash 是不一样的,sh 作为一种古老的 Shell,在 Linux 中已经基本上被 继任者 bash 代替了,但是那些 autoconf 的脚本依然继承了 sh 这个古老的惯性,也是为了兼容其他的系统吧,比如在 FreeBSD 中,默认安装就是没有 bash 的。

所以,倒也不是哪一个好或者是哪一个不好,就是大家都习惯了,反正也没有什么太大的问题,几十年了也不好再改了。 原因很简单,历史习惯+没人做。

说python不能做shell的我就呵呵了,知道scsh吗?scheme都能做shell凭啥python不能?说起来丢人,当初我还真动手要做一个pysh,弄了两周弄到兼容不同终端类型的时候实在不胜其烦放弃了。当时交互、解释执行、基本的iO、管道都已经有雏形了。 我觉得是完全可以取代的。给你们看一下 clojure 如何调用 shell:
<code class="language-clojure"><span class="p">(</span><span class="nf">require</span> <span class="o">'</span><span class="p">[</span><span class="nv">me.raynes.conch</span> <span class="ss">:refer</span> <span class="p">[</span><span class="nv">programs</span> <span class="nv">with-programs</span> <span class="nv">let-programs</span><span class="p">]</span> <span class="ss">:as</span> <span class="nv">sh</span><span class="p">])</span>

<span class="nv">user></span> <span class="p">(</span><span class="nf">programs</span> <span class="nv">echo</span><span class="p">)</span>
<span class="o">#</span><span class="ss">'user/echo</span>
<span class="nv">user></span> <span class="p">(</span><span class="nf">echo</span> <span class="s">"Hi!"</span><span class="p">)</span>
<span class="s">"Hi!\n"</span>
<span class="nv">user></span> <span class="p">(</span><span class="nf">programs</span> <span class="nv">cat</span><span class="p">)</span>
<span class="o">#</span><span class="ss">'user/cat</span>
<span class="nv">user></span> <span class="p">(</span><span class="nf">cat</span> <span class="p">{</span><span class="ss">:in</span> <span class="s">"hi"</span><span class="p">})</span>
<span class="s">"hi"</span>
<span class="nv">user></span> <span class="p">(</span><span class="nf">cat</span> <span class="p">{</span><span class="ss">:in</span> <span class="p">[</span><span class="s">"hi"</span> <span class="s">"there"</span><span class="p">]})</span>
<span class="s">"hi\nthere\n"</span>
</code>
对于复杂的逻辑,python具有模块化的特性,比shell更好用。

但是对于单条命令,用python是什么感受,每一条命令都要调用 os.xxx ,而且python的函数不像shell那样空格分隔,而是要加括号、逗号和引号的,那画面太美我不敢想。

所以最好的方案就是两者并存,直接敲命令用shell,写脚本用python。事实上很多linux发行版自带python,用python取代shell写脚本是没问题的。 @余天升 同学说的“惯性”这一点很有道理,但身边有不少人,用 bash 多年之后在别人的推荐下改用了 zsh (包括我),几天就完全切换完成了。在得知 Debian 系中 vi 只是 vim 的别名之后,养成打 vim 而不是 vi 的习惯的,也大有人在。因此,我认为特殊的不是 bash,而是 shell 这一类东西。shell 和其他脚本语言的区别是很重要的。
所谓“shell”,首先得是操作系统界面(这也是 shell 的原义),其次才是一个编程语言。而操作系统的职能中,文件系统和进程管理是两块很重要的地方。因此 shell 十分强调文件命令,这是其他脚本语言所不具备的。具体强调的方式,有语义上的,也有语法上的。
考虑最简单的,用 vim 打开文件 a.c,用 shell 写是:
<code class="language-text">vim a.c
</code>
很显然,bash更简洁 Python/Ruby/Perl 没有取代 Bash 的必要,Bash 是一个 Domain-Specific Language,而 Python 是个 General-purpose Programming Language,语言本身存在的目的本就不同,这也正是 DSL 存在的意义,可以参看维基百科相关条目。

我们讨论这个问题的前提是在 *nix 的背景下,那就应该从 *nix 自身的发展历史寻找原因,也就不难理解为什么 Python 永远不会做为 Shell 的替代存在。

Unix 的初期硬件条件的限制决定了 *nix 的设计哲学,其中最重要的两点就是:一、一个工具只做一件事,并把它做好;二、工具之间通过 plain text 进行数据交换。这样的设计降低了系统的复杂度,只需要 Shell 这样的胶水语言通过搭积木的方式即可完成很多复杂的任务。由于并不需要复杂的数据结构操作,Shell 不需要成为像 Python 或者 Perl 这样完整的程序语言,而且这一条件到现在也没有发生变化。

这里我比较赞同 @yegel 的观点,至于 @狼大人 对于 Bash 语法的吐槽,我相信在未来相当长一段时间 Bash 的语法不会彻底的改变。因为在 *nix 的世界里,Shell 的实现并不只有 Bash,可移植性是一个很重要的因素,被 @狼大人 吐槽的那些奇葩语法大部分都是 POSIX 定义的,也正是要感谢 POSIX 的存在,我们才能享受 *nix 带来的各种好处。

另外,具有交互模式的语言并不一定就能做为 Shell,成为 Shell 的一个必要条件是符合 *nix 的设计哲学,成为一个胶水语言,做为工具之间沟通的媒介,至少实现 pipe 是必不可少的。 因为:
BASH 是拿来“用”的
python 是拿来““的 python?你想每次都call(["ls", "path"])一次么?打括号一点都不好玩=。=
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn