这不是我想要的 shell (2011-05-08)

世上本没有shell,命令多了,也就成了shell。
——Pope


要说shell,就不能不谈起Unix的Keep It Simple Stupid理念。Unix社区崇尚简洁、专注,鼓励一个工具只做一件事,做好这件事。当你需要完成一项复杂的工作时,分解,细化,再交给相应的小工具去执行。这样就需要提供一种机制把各个工具连接起来。所以,在我开来,学习shell重在掌握任务分解和命令间的互联。

当然,你还会发现,shell的用法很奇怪,毕竟它是个很古老的东西了,包容各种历史遗留也是无奈之选。


其实,本文是一篇Learning the Bash Shell (3rd)的读书笔记。

shell是一种用户与类Unix操作系统之间以文字方式进行交互的媒介。还有其他的交互形式,比如图形界面。

shell命令一般是祈使句 如:去 给老子 拿瓶水来。

shell命令先是一个动词,紧接着若干副词(option)和名词(argument)(也可能没有)。

操作的对象大多是文件(Unix里几乎所有东西都是文件)。文件分为普通文件(文本),可执行文件和目录。

目录可以包括若干子目录,包括本目录(.)和父目录(..)。目录被组织成树形结构,用路径来标示。

可以明确指定shell操作的对象的绝对路径,如果不说就默认是在当前目录下。当前目录虽然被称为目录却没有物理对应,是一个概念上的浮动地址,可以通过pwd(print the working directory,你看多怪的名字,不知道的还以为是password呢)命令来查看,还可以用cd命令(change the working directory)来修改。此外还有主目录(~)和操作记录中的上一目录(-)。

shell的操作对象可以是具体名词(如某个文件名),也可以是抽象名词(用来描述某一特征,需要用到通配符(wildcard))。

通配符有三种基本模式:

匹配任一字符、匹配任意字符、匹配字符集。

!, \*, […], [!…], {…}

Unix将I/O设备统一看作文件,并把I/O看作处理任意长的字节流。

Unix把I/O流简化为标准输入输入(standard input)、标准输出(standard output)和标准错误输出(standard error output)三个端口。输入流默认为键盘,输出和错误流默认为显示屏。如果需要,可以将这些端口映射到其他设备或文件上(重定向)。

Unix下的小工具往往只专注于某项处理。数据被不同的小工具一道道筛选、加工,最后得到想要的结果。正是因为专注,让它们更容易组合起来构建复杂的工具。

奇怪的命名

虽然shell命令的命名也不是无章可循,但总归是很奇怪的。以下是几个常用的工具:

但比起那些预设变量,这还算好的。

比如位置参数,人家名字直接叫1, 2, ⋯⋯要想取到它们的值,前面加$($var其实是${var}的简写),即$1, $2, ⋯⋯。还有0(脚本文件的名字)、*(所有位置参数构成的字符串,用IFS(Internal Field Separator)的首字符作分隔符)、@("$1" "$2" ... "$N")、#(位置参数的个数)⋯⋯

不带参数的cat就像while true { echo input }

有管道还不够吗

cat是用来解释重定向的绝佳例子: cat < file1 > file2 等价于cp file1 file2command < filename,表示command从某个文件而不是标准输入拿到数据; command > filename,表示command将数据输出到某个文件而不是标准输出。

我觉得这个设计很好,但记法太屎。我宁愿多敲几个字,把从哪输入,输出到哪明确清楚了(比如: file1 > cat > file2)而不是把<>作为前缀贴到操作对象前面。

除了重定向输出到某个文件,你还可以把输出作为其他命令的输入直接导入(管道pipe,用|表示。这个记法也很屎,体现不出方向来,虽然知道是从左到右。为什么不能和重定向统一起来呢?!比如,$ cut -d: -f1 < /etc/passwd | sort | lp写成/etc/passwd > cut -d: -f1 > sort > lp的形式。可能是于当初把命令设计成前缀形式有关吧,如果当初设计成中缀形式并把命令也看成文件(命令本来就是内存里的一个文件),也许会方便很多)。

文本编辑原来这么阳春白雪

bash的emacs-mode对文本编辑提供很精细的控制:对字符的操作(^B, ^F, ^D, )、对单词的操作(⎋B, ⎋F, ⎋D, ⎋)、对整句的操作(^A, ^E, ^K, Y(找回前一次被删掉的东西)),甚至是对历史记录的操作(P(相当于↑), ^N(相当于↓), ^R)。

但emacs-mode最强大的功能还得是文本补全()。当你敲入几个字符并按下,可能会出现四种情况:

  • 没有以这些字符开头的词,shell会小叫一声beep;
  • 找到一个唯一的匹配,shell会补全它,并附带一个空格方便你敲其他字符;
  • 如果找到一个唯一匹配的目录,shell会补全文件名,并附上一个斜杠(/);
  • 如果有多个匹配可能,shell会补上这些可能匹配的最长前缀。

如果你想知道都有哪些可能的选择,敲两下(或者按⎋-?,它会显示所有可能选择)。
shell提供了很多快捷键来补全不同类型的名字(比如,⎋-/ 专门补文件名,⎋-~专补用户名,⎋-!专补命令名⋯⋯)
既然提到了emacs-mode,不用想也能知道肯定有个vi-mode。

vi最著名的就是用h, j, k, l作为←↓↑→。这得追溯到当初Bill Joy用ADM-3a开发vi,这种机器的h, j, k, l键上分别有四个←↓↑→小箭头,所以后面你知道的。

vi-mode和vi一样,也有两种模式(输入模式和控制模式)。在输入模式下,你可以键入、删除(⌫, ^W)。按下 ⎋ 可以进入控制模式。这个模式下,可以用单键来控制移动(h, l, b, w, 0, $)(很喜欢这种单键控制的方式,其实很多软件都可以借鉴。如果你不用编辑文字,干嘛要用control、shift这类的辅助键。这就好像有名字空间你不用,非得都搞成全家变量一样)。你不光可以移动一个字符(h, l)、一个单词(b, w),甚至还可以移动到某个特定的字符上(F-×, f-×,×表示任意字符)按下i(或a, I(等效于0i), A (等效于$a), R (与r略有不同,r只替换一个字符而且不会进入输入模式,即你不能再键入其他字符))切回输入模式。控制模式下还有个不得不提的命令——撤销(u, undo)。另外“.”也很有用,它反复执行上一次的操作。
vi也有文本补全,不过不是
,而是进入控制模式按反斜杠(/)。

一直觉得vi很有意思,设计很精巧,像一门微型语言。比如删除操作,按下d(delete)之后不会有什么变化,还要指定删除的方向(向前还是向后)和长度(字符还是单词还是整句,是当前光标位置到行首还是到行尾)。这不是v. + adv. + n. 结构么!而且一个动作可以有多个说法(比如删除整句,可以用dd,也可以用0d$)。让你感觉它不是一堆互不相干的快捷键,而是一句意义明确的指示。

命令行工具一个总的印象就是太费脑子,这里指的是要记的东西太多,不如GUI直观。但好处就在于它能控制得很精细,不像GUI,界面设计成什么样就只有哪些功能。

到底0是真是假

在流程控制中,shell用返回状态作为逻辑判断的结果。这样,0(在[...]中)就表示真,其他返回码均表示假。但在算术表达式($((...))$[...])中,0却是假,1才是真。而算术式的另一种形式((...))却用0作为真,1为假

丑陋的语法

如果说if...then...fi是bash的特色的话,bash的case这是巨丑陋:

case expression in
    pattern1 )  
        statements ;;  
    pattern2 )  
        statements ;;   
        ...  
esac

你就不能正常一点?!至少对称一点,别弄出半边括号来好不。
还有,按理说shell的语法是不依赖空格或是换行的。可你看看赋值语句,多了空格它不干,再看看[ ... ]少了空格它也不干。而在for, while, select里do如果新起一行就不用打分号。

shell语法看似统一,其实很混乱。这货不是一门语言,而是一堆微型语言,虽然每个都很简单,但要想全都记住却有不小难度。

P.S. Learning the bash Shell似乎没有继承Learning系列简单明了的衣钵,看似很全,其实毫无系统。示例晦涩,讲解不清,比如对getopts里OPTSTRING(Mac下好像是这个,书中是OPTARG)的说明,OPTSTRING是一个由option及其所带参数构成的一个序列,而OPTIND是OPTSTRING里下一个要处理的option的下标(不敢举例,怕自己理解有误)。

我想要的shell

首先互联功能必须很强大;
灵活的语法(不依赖空格神马的,不限定格式);
统一的语法;

⋯⋯
(cont.)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,444评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,867评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,157评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,312评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,673评论 3 289
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,802评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,010评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,743评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,470评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,696评论 2 250
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,187评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,538评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,188评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,127评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,889评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,741评论 2 274

推荐阅读更多精彩内容