2006年12月7日星期四

1.7. 输入和输出

1.7. 输入和输出

软件环境真正科学的环境以某些场合下某些人(譬如,不是什么委员会员)提出一个概念上简单但是内涵却丰富的见解而趋向快速且深刻的发展。UNIX的输入输出规则就包含属于这种见解,它属于类似LISP语言的一流创新,以及关系数据模型和面向对象程序。

UNIX I/O规则是建立在两个出色的简单见解上。首先,文件I/O采取任意长度和排列字符的形式。与之相对的是,一些陈旧的过时的文件系统复杂的I/O规则(譬如,“block”,“record”,“card image”等等。)。其次,所有在系统中的物品或接受的数据都处理为一个文件;这包括如磁盘和终端的硬件设备。陈旧的文件因设备而不同。以上两种意见使系统programmers’非常舒适。

1.7.1. 标准 I/O

根据约定,UNIX程序都有一个称为标准输入的方式接受输入,一个称为标准输出的方式输出,以及一个称为标准错误(standard error output, usually shortened to standard error)输出的方式输出错误信息。当然程序可以有更好的方式输入输出方式,详见Chapter 7

标准I/O是为终端用户首个拥有明确设计的规则,而非通常使用的涉及打孔机的旧风格。正因为UNIX shell提供了用户接口,所以shell能设计的和标准I/O非常完美的结合也就不足为奇。

所以的Shell掌控标准I/O的基本方法都是同样的。每个您在终端或者工作站调用的程序都有三个基本I/O通道,标准输入是您的键盘,标准输出或错误使您的屏幕或者窗口。譬如,mail工具在标准输出上显示您的消息,而且当您使用它发消息给其他用户时,它从标准输入上接受您的输入。这意味这您在显示器上查看消息并在使用您的键盘输入新的消息。

若是有必要,您可以重定向输入和输出或是用一个文件来代替。若是您想要发送某人一份内容为已存在文件的邮件,您可以重定向邮件的标准输入使它可以读入文件来代替您的键盘。

您还可以使用通道符连接程序,使用一个程序的标准输出直接定向到另一个程序的标准输入;譬如,您可以使用邮件的输出定向到lp程序以便消息可以替代显示在显示器上而打印出来。

这使得使用UNIX工具创建模块或者大程序成为可能。很多UNIX有用程序使用这种方法:他们分别从输入文本过滤操作中得到特别类型的输入来执行。虽然这不是UNIX工具的规范,但他是shell使用的生产力。比较流行的过滤工具在Table 1-5列出。

Table 1-5. 流行的 UNIX 数据过滤工具

工具

意图

cat

拷贝输入到输出

grep

从输入中搜索字符串

sort

将输入按行排列

cut

从输入中取出一列

sed

Perform editing operations on input(在输入中完成编辑操作)

tr

Translate characters in the input to other characters(转换输入字符到另一个字符集)

您也许使用过这些工具或者注意到他们可以使用输入文件的名称作为参数且在标准输出上产生输出。您可能不知道,不管如何,所有这些工具(包括其他UNIX工具)若是您忽略参数便接受从标准输入的输入。[13]

[13] 若是特别的UNIX工具不接受您使用文件名参数的标准输入,试着使用减号(-)作为参数。一些UNIX系统提供标准出入为文件,所以您可以试着提供文件/dev/stdin作为输入文件参数。

譬如,最基础的使用是cat,一个简单拷贝输入到输出的工具。若是您输入cat跟随文件名参数,它会在您屏幕上打印出文件内容。但是若是您没用参数的调用它,它会等待标准输入且拷贝其内容到标准输出上。尝试下:cat会等待您输入一行的文本;当您输入回车,cat会返回您重复文本。停止这个过程,在一行的开始点击CTRL-D。当您输入CTRL-D您会看到^D。以下为可能看到的内容:

$ cat
Here is a line of text.
Here is a line of text.
This is another line of text.
This is another line of text.
^D
$ 

1.7.2. I/O Redirection(I/O重定向)

cat是英文单词连接(catenate的简写,也就是连接起来。它接受多个文件名参数且拷贝他们到标准输出。但是让我们现在假装,cat和其他工具不接受文件名参数而只接受标准输入。正如我们上面所说,shell使您重定向标准输入为一个文件。符号 < 文件名 达到此效果;它设置事务在终端由文件替代标准输入。

譬如,若是您有一个文件叫cheshire包含了写文本内容,那么cat <>会显示cheshire的内容到您的终端上。sort <>会以行排列cheshire文件的内容并显示到您的终端上(记住:我们假装这些工具不接受文件名参数。)

同样的,命令 > 文件名 导致命令的标准输出重定向到命名的文件上。著名的“标准”例子是date > now date命令打印出当前的日期和时间到标准输出上;先前的命令保存输出到一个称为now的文件上。

输入和输出重定向可以组合起来。譬如:命令cp是通常用来拷贝文件;若是因为一些原因它不存在或者出错,您可以使用cat来完成:

$ cat <  file1  >  file2 

这与cp file1 file2相似。

1.7.3. Pipelines(通道行)

将命令重定向输出为另外命令的替代文件的标准输入也是可能的。这种概念叫做通道(pipe),符号为|。命令行包含由通道联系的两个或更多命令叫做通道行。

通道经常使用在more命令中,这个命令除了会一屏一屏的显示输出外和cat很相像,它暂停以等带用户输入,SPACE(下一屏),RETURN(下一行),或者其他命令。若是您在一个有很多文件的目录下,想要详细的看到他们,ls –l |more会每次为您显示详细的清单。

通道行(Pipelines)可以非常复杂,并且他们可以与其他的I/O定向符整合。每次想要在一屏下排列文件cheshire清单,输入sort <>。想要打印这些来代替您终端上的显示,输入sort <>。

这有很多复杂的例子。文件/etc/passwd储存了UNIX系统中关于用户的信息。此文件每一行包含用户的登陆名(login name,用户标识(user ID number,加密密码,主目录,登陆shell,和其他信息。每一行的第一部分是登陆名;每部分由冒号(:)来区分。这一行犹如:

cam:LM1c7GhNesD4GhF3iEHrH4FeCKB/:501:100:Cameron Newham:/home/cam:/bin/bash

要得到所有用户的排列清单,输入:

$ cut -d: -f1 < /etc/passwd | sort

(实际上,您可以忽略<,因为cut接受文件名参数。)这个cut命令从输入分离出首个由冒号分离(-d:)的部分(-f1)。全部的通道行会像如下这样显示:

adm
bin
cam
daemon
davidqc
ftp
games
gonzo
...


若是您像发送这些清单定向到打印机(代替您的屏幕),你可以像这样扩充通道行:

$ cut -d: -f1 < /etc/passwd | sort | lp

现在您会明白I/O定向和通道行如何支持UNIX建立模块理论。这些符号是非常简单和且强大。最重要的是,通道概念排除了用来为其它命令保存输出所需要的凌乱临时文件。

譬如,为了在其它操作系统(assuming that equivalent utilities are available...)命令行上做于同样的排列事情,你需要三个命令。在DECVAX/VMS系统上,他们显示类似这样:

$ cut [etc]passwd /d=":" /f=1 /out=temp1
$ sort temp1 /out=temp2
$ print temp2
$ delete temp1 temp2

经过充分的实践,您会发现您自己可以熟练输入强大的通道行命令,在一行内可以包括多个命令(以及临时文件)来完成系统操作。

2 条评论:

小草儿 说...

不错呀!

starluo 说...

开玩笑,也不看看谁干的