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

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

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

要说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命令的命名也不是无章可循,但总归是很奇怪的。以下是几个常用的工具:

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

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

比如位置参数,人家名字直接叫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。

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

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

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

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 (2011-05-08)》

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

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

我想要的shell

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

⋯⋯
(cont.)

    原文作者:Pope怯懦懦地
    原文地址: https://www.jianshu.com/p/498ebffde3eb
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞