查看原文
其他

Linux Shell 浅析

c.j 计算机与网络安全 2022-06-01

信息安全公益宣传,信息安全知识启蒙。

加微信群回复公众号:微信群QQ群16004488

加微信群或QQ群可免费索取:学习教程

教程列表见微信公众号底部菜单



Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。


实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。


一、Shell 简介


Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。

实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。


Linux提供了像MicrosoftWindows那样的可视的命令输入界面--X Window的图形用户界面(GUI)。它提供了很多桌面环境系统,其操作就像Windows一样,有窗口、图标和菜单,所有的管理都是通过鼠标控制。GNOME。


每个Linux系统的用户可以拥有他自己的用户界面或Shell,用以满足他们自己专门的Shell需要。


同Linux本身一样,Shell也有多种不同的版本。主要有下列版本的Shell:Bourne Shell:是贝尔实验室开发的。


BASH:是GNU的Bourne Again Shell,是GNU操作系统上默认的shell。


Korn Shell:是对Bourne SHell的发展,在大部分内容上与Bourne Shell兼容。


C Shell:是SUN公司Shell的BSD版本。


Z Shell:The last shell you’ll ever need! Z是最后一个字母,也就是终极Shell。它集成了bash、ksh的重要特性,同时又增加了自己独有的特性。


二、Shell 的使用


不论是哪一种Shell,它最主要的功用都是解译使用者在命令列提示符号下输入的指令。Shell 语法分析命令列,把它分解成以空白区分开的符号(token),在此空白包括了跳位键(tab)、空白和换行(New Line)。如果这些字包含了metacharacter,shell 将会评估(evaluate)它们的正确用法。另外,shell 还管理档案输入输出及幕后处理(background processing)。在处理命令列之后,shell 会寻找命令并开始执行它们。


Shell 的另一个重要功用是提供个人化的使用者环境,这通常在 shell 的初始化档案中完成(.profile、.login、.cshrc、.tcshrc 等等)。这些档案包括了设定终端机键盘和定义窗口的特征;设定变量,定义搜寻路径、权限、提示符号和终端机类型;以及设定特殊应用程序所需要的变量,例如窗口、文字处理程序、及程序语言的链接库。Korn shell 和 C shell 加强了个别化的能力:增加历程、别名、和内建变量集以避免使用者误杀档案、不慎签出、并在当工作完成时通知使用者。


Shell 也能当解译性的程序语言(interpreted programing language)。Shell 程序,通常叫做命令文件,它由列在档案内的命令所构成。此程序在编辑器中编辑(虽然也可以直接在命令列下写作程序,online scripting),由 UNIX 命令和基本的程序结构,例如变量的指定、测试条件、和循环所构成。您不需要编译 shell 命令档。Shell 本身会解译命令档中的每一行,就如同由键盘输入一样。shell 负责解译命令,而使用者则必须了解这些命令能做什么。下面列出了一些有用的命令和它们的使用方法。


三、shell入门基础必备


建立和运行shell程序


什么是shell程序呢?简单的说shell程序就是一个包含若干行shell或者linux命令的文件。像编写高级语言的程序一样,编写一个shell程序需要一个文本编辑器.如Ⅵ等。在文本编辑环境下,依据shell的语法规则,输入一些shell/linux命令行,形成一个完整的程序文件。


执行shell程序文件有三种方法:


(1)#chmod +x file(在/etc/profile中,加入export PATH=${PATH}:~/yourpath,就可以在命令行下直接运行,像执行普通命令一样)

(2)#sh file

(3)# . file

(4)#source file


在编写shell时,第一行一定要指明系统需要那种shell解释你的shell程序,如:#! /bin/bash,#! /bin/csh,/bin/tcsh,还是#! /bin/pdksh


shell中的变量


(1)常用系统变量


$ # :保存程序命令行参数的数目

$ ?:保存前一个命令的返回码

$ 0 :保存程序名

$ * :以("$1 $2...")的形式保存所有输入的命令行参数

$ @ :以("$1""$2"...)的形式保存所有输入的命令行参数


(2)定义变量


shell语言是非类型的解释型语言,不象用C++/JAVA语言编程时需要事先声明变量.给一个变量赋值,实际上就是定义了变量。


在linux支持的所有shell中,都可以用赋值符号(=)为变量赋值,如:


abc=9 (bash/pdksh不能在等号两侧留下空格)

set abc = 9 (tcsh/csh)


由于shell程序的变量是无类型的,所以用户可以使用同一个变量时而存放字符时而存放整数,如:


name=abc (bash/pdksh)

set name = abc (tcsh)


在变量赋值之后,只需在变量前面加一个$去引用,如:


echo $name


(3)位置变量


当运行一个支持多个命令行参数的shell程序时,这些变量的值将分别存放在位置变量里。其中第一个参数存放在位置变量1,第二个参数存放在位置变量2,依次类推...,shell保留。这些变量,不允许用户以令外的方式定义他们.同别的变量,用$符号引用他们。


shell中引号的使用方法


shell使用引号(单引号/双引号)和反斜线("\")用于向shell解释器屏蔽一些特殊字符,反引号(")对shell则有特殊意义,如:


abc="how are you" (bash/pdksh)

set abc = "how are you" (tcsh)


这个命令行把三个单词组成的字符串how are you作为一个整体赋值给变量abc。


abc1='$LOGNAME,how are you!' (bash/pdksh)

set abc1='$LOGNAME,how are you!' (tcsh)

abc2="$LOGNAME,how are you!" (bash/pdksh)

set abc2="$LOGNAME,how are you!" (tcsh)


LOGNAME变量是保存当前用户名的shell变量,假设他的当前值是:wang.执行完两条命令后,abc1的内容是:$LOGNAME,how are you!.而abc2的内容是;wang,how are you!.


象单引号一样,反斜线也能屏蔽所有特殊字符.但是他一次只能屏蔽一个字符,而不能屏蔽一组字符。反引号的功能不同于以上的三种符号.他不具有屏蔽特殊字符的功能.但是可以通过他将一个命令的运行结果传递给另外一个命令,如:


contents=`ls` (bash/pdksh)

set contents = `ls` (tcsh)


shell程序中的test命令


在bash/pdksh中,命令test用于计算一个条件表达式的值.他们经常在条件语句和循环语句中被用来判断某些条件是否满足。


test命令的语法格式:


test expression


或者


[expression]


在test命令中,可以使用很多shell的内部操作符.这些操作符介绍如下:


(1)字符串操作符 用于计算字符串表达式


test命令 | 含义


Str1 = str2 | 当str1与str2相同时,返回True

Str1! = str2| 当str1与str2不同时,返回True

Str | 当str不是空字符时,返回True

-n str | 当str的长度大于0时,返回True

-z str | 当str的长度是0时,返回True


(2)整数操作符具有和字符操作符类似的功能.只是他们的操作是针对整数


test表达式 | 含义


Int1 -eq int2|当int1等于int2时,返回True

Int1 -ge int2|当int1大于/等于int2时,返回True

Int1 -le int2|当int1小于/等于int2时,返回True

Int1 -gt int2|当int1大于int2时,返回True

Int1 -ne int2|当int1不等于int2时,返回True

(3)用于文件操作的操作符,他们能检查:文件是否存在,文件类型等


test表达式 | 含义


-d file |当file是一个目录时,返回 True

-f file |当file是一个普通文件时,返回 True

-r file |当file是一个可读文件时,返回 True

-s file |当file文件长度大于0时,返回 True

-w file |当file是一个可写文件时,返回 True

-x file |当file是一个可执行文件时,返回 True


(4)shell的逻辑操作符用于修饰/连接包含整数,字符串,文件操作符的表达式


test表达式 | 含义


! expr |当expr的值是False时,返回True

Expr1 -a expr2|当expr1,expr2值同为True时,返回True

Expr1 -o expr2|当expr1,expr2的值至少有一个为True时,返回True


注意:


tcsh shell 不使用test命令,但是tcsh中的表达式同样能承担相同的功能.tcsh

支持的表达式于C中的表达式相同.通常使用在if和while命令中。


tcsh表达式 | 含义


Int1 <= int2 |当int1小于/等于int2时,返回True

Int1 >= int2 |当int1大于/等于int2时,返回True

Int1 < int2 |当int1小于int2时,返回True

Int1 > int2 |当int1大于int2时,返回True

Str1 == str2 |当str1与str2相同时,返回True

Str1 != str2 |当str1与str2不同时,返回True

-r file |当file是一个可读文件时,返回True

-w file |当file是一个可写文件时,返回True

-x file |当file是一个可执行文件时,返回True

-e file |当file存在时,返回True

-o file |当file文件的所有者是当前用户时,返回True

-z file |当file长度为0时,返回True

-f file |当file是一个普通文件时,返回True

-d file |当file是一个目录时,返回True

Exp1 || exp2 |当exp1和exp2的值至少一个为True时,返回True

Exp1 && exp2 |当exp1和exp2的值同为True时,返回True

! exp |当exp的值为False时,返回True


四、Linux主要shell命令详解


shell是用户和Linux操作系统之间的接口。Linux中有多种shell,其中缺省使用的是Bash。本章讲述了shell的工作原理,shell的种类,shell的一般操作及Bash的特性。


什么是shell


Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。


shell是用户和Linux内核之间的接口程序,如果把Linux内核想象成一个球体的中心,shell就是围绕内核的外层。当从shell或其他程序向Linux传递命令时,内核会做出相应的反应。


shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给Linux核心。


有一些命令,比如改变工作目录命令cd,是包含在shell内部的。还有一些命令,例如拷贝命令cp和移动命令mv,是存在于文件系统中某个目录下的单独的程序。对用户而言,不必关心一个命令是建立在shell内部还是一个单独的程序。


shell首先检查命令是否是内部命令,若不是再检查是否是一个应用程序(这里的应用程序可以是Linux本身的实用程序,如ls和rm,也可以是购买的商业程序,如xv,或者是自由软件,如emacs)。然后shell在搜索路径里寻找这些应用程序(搜索路径就是一个能找到可执行程序的目录列表)。如果键入的命令不是一个内部命令并且在路径里没有找到这个可执行文件,将会显示一条错误信息。如果能够成功找到命令,该内部命令或应用程序将被分解为系统调用并传给Linux内核。


shell的另一个重要特性是它自身就是一个解释型的程序设计语言,shell程序设计语言支持绝大多数在高级语言中能见到的程序元素,如函数、变量、数组和程序控制结构。shell编程语言简单易学,任何在提示符中能键入的命令都能放到一个可执行的shell程序中。


当普通用户成功登录,系统将执行一个称为shell的程序。正是shell进程提供了命令行提示符。作为默认值(TurboLinux系统默认的shell是BASH),对普通用户用“$”作提示符,对超级用户(root)用“#”作提示符。


一旦出现了shell提示符,就可以键入命令名称及命令所需要的参数。shell将执行这些命令。如果一条命令花费了很长的时间来运行,或者在屏幕上产生了大量的输出,可以从键盘上按ctrl+c发出中断信号来中断它(在正常结束之前,中止它的执行)。


当用户准备结束登录对话进程时,可以键入logout命令、exit命令或文件结束符(EOF)(按ctrl+d实现),结束登录。


我们来实习一下shell是如何工作的。


$ make work

make:***No rule to make target ‘work’. Stop.

$


注释:make是系统中一个命令的名字,后面跟着命令参数。在接收到这个命令后,shell便执行它。本例中,由于输入的命令参数不正确,系统返回信息后停止该命令的执行。


在例子中,shell会寻找名为make的程序,并以work为参数执行它。make是一个经常被用来编译大程序的程序,它以参数作为目标来进行编译。在 “make work”中,make编译的目标是work。因为make找不到以work为名字的目标,它便给出错误信息表示运行失败,用户又回到系统提示符下。


另外,用户键入有关命令行后,如果shell找不到以其中的命令名为名字的程序,就会给出错误信息。例如,如果用户键入:


$ myprog

bash:myprog:command not found

$


可以看到,用户得到了一个没有找到该命令的错误信息。用户敲错命令后,系统一般会给出这样的错误信息。


shell的种类


Linux中的shell有多种类型,其中最常用的几种是Bourne shell(sh)、C shell(csh)和Korn shell(ksh)。三种shell各有优缺点。Bourne shell是UNⅨ最初使用的shell,并且在每种UNⅨ上都可以使用。Bourne shell在shell编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种shell。Linux操作系统缺省的shell是Bourne Again shell,它是Bourne shell的扩展,简称Bash,与Bourne shell完全向后兼容,并且在Bourne shell的基础上增加、增强了很多特性。Bash放在/bin/bash中,它有许多特色,可以提供如命令补全、命令编辑和命令历史表等功能,它还包含了很多C shell和Korn shell中的优点,有灵活和强大的编程接口,同时又有很友好的用户界面。


C shell是一种比Bourne shell更适于编程的shell,它的语法与C语言很相似。Linux为喜欢使用C shell的人提供了Tcsh。Tcsh是C shell的一个扩展版本。Tcsh包括命令行编辑、可编程单词补全、拼写校正、历史命令替换、作业控制和类似C语言的语法,它不仅和Bash shell是提示符兼容,而且还提供比Bash shell更多的提示符参数。


Korn shell集合了C shell和Bourne shell的优点并且和Bourne shell完全兼容。Linux系统提供了pdksh(ksh的扩展),它支持任务控制,可以在命令行上挂起、后台执行、唤醒或终止程序。


Linux并没有冷落其他shell用户,还包括了一些流行的shell如ash、zsh等。每个shell都有它的用途,有些shell是有专利的,有些能从Internet网上或其他来源获得。要决定使用哪个shell,只需读一下各种shell的联机帮助,并试用一下。


用户在登录到Linux时由/etc/passwd文件来决定要使用哪个shell。例如:


# fgrep lisa /etc/passwd

lisa:x:500:500:TurboLinux User:/home/lisa:/bin/bash

shell被列每行的末尾(/bin/bash)。


由于Bash是Linux上缺省的shell,本章主要介绍Bash及其相关知识。


shell命令


用户登录到Linux系统时,可以看到一个shell提示符,标识了命令行的开始。用户可以在提示符后面输入任何命令及参数。例如:


$ date

二 11 23 01:34:58 CST 1999

$


用户登录时,实际进入了shell,它遵循一定的语法将输入的命令加以解释并传给系统。命令行中输入的第一个字必须是一个命令的名字,第二个字是命令的选项或参数,命令行中的每个字必须由空格或TAB隔开,格式如下:


$ Command Option Arguments


选项和参数


选项是包括一个或多个字母的代码,它前面有一个减号(减号是必要的,Linux用它来区别选项和参数),选项可用于改变命令执行的动作的类型。例如:


$ ls

motd passwd

$


这是没有选项的ls命令,可列出当前目录中所有文件,只列出各个文件的名字,而不显示其他更多的信息。


$ ls -l

total 2

-rw-r--r-- 2 wzh book 22 Apr 20 20:37 motd

-rw-r--r-- 2 wzh book 796 Apr 20 20:37 passwd

$


加入-l选项,将会为每个文件列出一行信息,诸如数据大小和数据最后被修改的时间。


大多数命令都被设计为可以接纳参数。参数是在命令行中的选项之后键入的一个或多个单词,例如:


$ ls -l text

-rw-r--r-- 2 wzh book 22 Apr 20 20:37 motd

-rw-r--r-- 2 wzh book 796 Apr 20 20:37 passwd

$


将显示text目录下的所有文件及其信息。


有些命令,如ls可以带参数,而有一些命令可能需要一些最小数目的参数。例如,cp命令至少需要两个参数,如果参数的数目与命令要求不符,shell将会给出出错信息。例如:


$ cp -i mydata newdata


注意:命令行中选项先于参数输入。


命令行特征


命令行实际上是可以编辑的一个文本缓冲区,在按回车之前,可以对输入的文本进行编辑。比如利用BACKSPACE键可以删除刚键入的字符,可以进行整行删除,还可以插入字符,使得用户在输入命令,尤其是复杂命令时,若出现键入错误,无须重新输入整个命令,只要利用编辑操作,即可改正错误。


利用上箭头可以重新显示刚执行的命令,利用这一功能可以重复执行以前执行过的命令,而无须重新键入该命令。


bash保存着以前键入过的命令的列表,这一列表被称为命令历史表。按动上箭头,便可以在命令行上逐次显示各条命令。同样,按动下箭头可以在命令列表中向下移动,这样可以将以前的各条命令显示在命令行上,用户可以修改并执行这些命令。


在一个命令行中还可以置入多个命令,用分号将各个命令隔开。例如:


$ ls -F;cp -i mydata newdata


也可以在几个命令行中输入一个命令,用反斜杠将一个命令行持续到下一行。


$ cp –i

mydata

newdata


上面的cp命令是在三行中输入的,开始的两行以反斜杠结束,把三行作为一个命令行。


shell中的特殊字符


shell中除使用普通字符外,还可以使用一些具有特殊含义和功能的特殊字符。在使用它们时应注意其特殊的含义和作用范围。下面分别对这些特殊字符加以介绍。


⒈ 通配符


通配符用于模式匹配,如文件名匹配、路经名搜索、字符串查找等。常用的通配符有*、?和括在方括号[ ]中的字符序列。用户可以在作为命令参数的文件名中包含这些通配符,构成一个所谓的“模式串”,在执行过程中进行模式匹配。


* 代表任何字符串(长度可以不等),例如:“f*”匹配以f打头的任意字符串。但应注意,文件名前的圆点(.)和路经名中的斜线(/)必须显式匹配。例如“*”不能匹配.file,而“.*”才可以匹配.file。


? 代表任何单个字符。


[] 代表指定的一个字符范围,只要文件名中[ ]位置处的字符在[]中指定的范围之内,那么这个文件名就与这个模式串匹配。方括号中的字符范围可以由直接给出的字符组成,也可以由表示限定范围的起始字符、终止字符及中间的连字符(-)组成。例如,f [a- d] 与f [abcd]的作用相同。Shell将把与命令行中指定的模式串相匹配的所有文件名都作为命令的参数,形成最终的命令,然后再执行这个命令。


通配符含义举例


* 当前目录下所有文件的名称。


*Text* 当前目录下所有文件名中包含有Text的文件的名称。


[ab-dm]* 当前目录下所有以a、b、c、d、m开头的文件的名称。


[ab-dm]? 当前目录下所有以a、b、c、d、m开头且后面只跟有一个字符的文件的名称。


/usr/bin/?? 目录/usr/bin下所有名称为两个字符的文件的名称。


特别需要注意的是,连字符“-”仅在方括号内有效,表示字符范围,如在方括号外面就成为普通字符了。而*和?只在方括号外面是通配符,若出现在方括号之内,它们也失去通配符的能力,成为普通字符了。例如,模式“- a[*?]abc”中只有一对方括号是通配符,*和?均为普通字符,因此,它匹配的字符串只能是- a*abc和- a?abc。


说明一下使用通配符时需要注意的一些问题。由于*、?和[]对于shell来说具有比较特殊的意义,因此在正常的文件名中不应出现这些字符。特别是在目录名中不要出现它们,否则Shell匹配起来可能会无穷的递归下去。另外要注意的一点是:如果目录中没有与指定的模式串相匹配的文件名,那么Shell将使用此模式串本身作为参数传给有关命令。这可能就是命令中出现特殊字符的原因所在。


⒉ 引号


在shell中引号分为三种:单引号,双引号和反引号。


单引号 ‘


由单引号括起来的字符都作为普通字符出现。特殊字符用单引号括起来以后,也会失去原有意义,而只作为普通字符解释。例如:


$ string=’$PATH’

$ echo $string

$PATH

$


可见$保持了其本身的含义,作为普通字符出现。


双引号 “


由双引号括起来的字符,除$、、’、和”这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待。对于$来说,就是用其后指定的变量的值来代替这个变量和$;对于而言,是转义字符,它告诉shell不要对其后面的那个字符进行特殊处理,只当作普通字符即可。可以想见,在双引号中需要在前面加上的只有四个字符$,,’和”本身。而对”号,若其前面没有加,则Shell会将它同前一个”号匹配。


例如,我们假定PATH的值为.:/usr/bin:/bin,输入如下命令:


$ TestString=”$PATH\”$PATH”

$ echo $TestString

.:/usr/bin:/ bin”$PATH

$


可以自己试一下在第二个双引号之前不加会产生什么结果。


反引号 `


反引号(`)这个字符所对应的键一般位于键盘的左上角,不要将其同单引号(’)混淆。反引号括起来的字符串被shell解释为命令行,在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分。例如:


$ pwd

/home/xyz

$ string=”current directory is `pwd`”

$ echo $string

current directour is /home/xyz

$


shell执行echo命令时,首先执行`pwd`中的命令pwd,并将输出结果/home/xyz取代`pwd`这部分,最后输出替换后的整个结果。


利用反引号的这种功能可以进行命令置换,即把反引号括起来的执行结果赋值给指定变量。例如:


$ today=`date`

$ echo Today is $today

Today is Mon Apr 15 16:20:13 CST 1999

$


反引号还可以嵌套使用。但需注意,嵌套使用时内层的反引号必须用反斜线()将其转义。例如:


$ abc=`echo The number of users is `who| wc-l``

$ echo $abc

The number of users is 5

$


在反引号之间的命令行中也可以使用shell的特殊字符。Shell为得到``中命令的结果,它实际上要去执行``中指定的命令。执行时,命令中的特殊字符,如$,”,?等又将具有特殊含义,并且``所包含的可以是任何一个合法的Shell命令,如:


$ ls

note readme.txt Notice Unix.dir

$ TestString=”`echo $HOME ` ` ls [nN]*`”

$ echo $TestString

/home/yxz note Notice

$


其他情况,可自行试之。


注释符


在shell编程中经常要对某些正文行进行注释,以增加程序的可读性。在Shell中以字符“#”开头的正文行表示注释行。


此外还有一些特殊字符如:用于输入/输出重定向与管道的<;、>;、<<;、>>;和|;执行后台命令的&;;命令执行操作符&&;和||及表示命令组的{}将在下面各小节中加以介绍。


标准输入/输出和重定向


⒈ 标准输入与输出


我们知道,执行一个shell命令行时通常会自动打开三个标准文件,即标准输入文件(stdin),通常对应终端的键盘;标准输出文件(stdout)和标准错误输出文件(stderr),这两个文件都对应终端的屏幕。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。


我们以cat命令为例,cat命令的功能是从命令行给出的文件中读取数据,并将这些数据直接送到标准输出。若使用如下命令:


$ cat config


将会把文件config的内容依次显示到屏幕上。但是,如果cat的命令行中没有参数,它就会从标准输入中读取数据,并将其送到标准输出。例如:


$ cat

Hello world

Hello world

Bye

Bye

<ctrl+d>

$


用户输入的每一行都立刻被cat命令输出到屏幕上。


另一个例子,命令sort按行读入文件正文(当命令行中没有给出文件名时,表示从标准输入读入),将其排序,并将结果送到标准输出。下面的例子是从标准输入读入一个采购单,并将其排序。


$ sort

bananas

carrots

apples

<ctrl+d>

apples

bananas

carrots

$


这时我们在屏幕上得到了已排序的采购单。


直接使用标准输入/输出文件存在以下问题:


输入数据从终端输入时,用户费了半天劲输入的数据只能用一次。下次再想用这些数据时就得重新输入。而且在终端上输入时,若输入有误修改起来不是很方便。


输出到终端屏幕上的信息只能看不能动。我们无法对此输出作更多处理,如将输出作为另一命令的输入进行进一步的处理等。


为了解决上述问题,Linux系统为输入、输出的传送引入了另外两种机制,即输入/输出重定向和管道。


⒉ 输入重定向


输入重定向是指把命令(或可执行程序)的标准输入重定向到指定的文件中。也就是说,输入可以不来自键盘,而来自一个指定的文件。所以说,输入重定向主要用于改变一个命令的输入源,特别是改变那些需要大量输入的输入源。

例如,命令wc统计指定文件包含的行数、单词数和字符数。如果仅在命令行上键入:


$ wc


wc将等待用户告诉它统计什么,这时shell就好象死了一样,从键盘键入的所有文本都出现在屏幕上,但并没有什么结果,直至按下<ctrl+d>;,wc才将命令结果写在屏幕上。


如果给出一个文件名作为wc命令的参数,如下例所示,wc将返回该文件所包含的行数、单词数和字符数。


$ wc /etc/passwd

20 23 726 /etc/passwd

$


另一种把/etc/passwd文件内容传给wc命令的方法是重定向wc的输入。输入重定向的一般形式为:命令<;文件名。可以用下面的命令把wc命令的输入重定向为/etc/passwd文件:


$ wc < /etc/passwd

20 23 726

$


另一种输入重定向称为here文档,它告诉shell当前命令的标准输入来自命令行。here文档的重定向操作符使用<<;。它将一对分隔符(本例中用delim表示)之间的正文重定向输入给命令。下例将一对分隔符delim之间的正文作为wc命令的输入,统计出正文的行数、单词数和字符数。


$ wc<<delim

>this text forms the content

>of the here document,which

>continues until the end of

>text delimter

>delim

4 17 98


在<<;操作符后面,任何字符都可以作为正文开始前的分隔符,本例中使用delim作为分隔符。here文档的正文一直延续到遇见另一个分隔符为止。第二个分隔符应出现在新行的开头。这时here文档的正文(不包括开始和结束的分隔符)将重新定向送给命令wc作为它的标准输入。


由于大多数命令都以参数的形式在命令行上指定输入文件的文件名,所以输入重定向并不经常使用。尽管如此,当要使用一个不接受文件名作为输入参数的命令,而需要的输入内容又存在一个文件里时,就能用输入重定向解决问题。


3、输出重定向


输出重定向是指把命令(或可执行程序)的标准输出或标准错误输出重新定向到指定文件中。这样,该命令的输出就不显示在屏幕上,而是写入到指定文件中。


输出重定向比输入重定向更常用,很多情况下都可以使用这种功能。例如,如果某个命令的输出很多,在屏幕上不能完全显示,那么将输出重定向到一个文件中,然后再用文本编辑器打开这个文件,就可以查看输出信息;如果想保存一个命令的输出,也可以使用这种方法。还有,输出重定向可以用于把一个命令的输出当作另一个命令的输入(还有一种更简单的方法,就是使用管道,将在下面介绍)。


输出重定向的一般形式为:命令>;文件名。例如:


$ ls > directory.out

$ cat directory.out

ch1.doc ch2.doc ch3.doc chimp config mail/ test/

$


将ls命令的输出保存为一个名为directory.out的文件。


注:如果>;符号后边的文件已存在,那么这个文件将被重写。


为避免输出重定向中指定文件只能存放当前命令的输出重定向的内容,shell提供了输出重定向的一种追加手段。输出追加重定向与输出重定向的功能非常相似,区别仅在于输出追加重定向的功能是把命令(或可执行程序)的输出结果追加到指定文件的最后,而该文件原有内容不被破坏。


如果要将一条命令的输出结果追加到指定文件的后面,可以使用追加重定向操作符>>;。形式为:命令>>;文件名。例如:


$ ls *.doc>>directory.out

$ cat directory.out

ch1.doc ch2.doc ch3.doc chimp config mail/ test/

ch1.doc ch2.doc ch3.doc

$


和程序的标准输出重定向一样,程序的错误输出也可以重新定向。使用符号2>;(或追加符号2>>;)表示对错误输出设备重定向。例如下面的命令:


$ ls /usr/tmp 2> err.file


可在屏幕上看到程序的正常输出结果,但又将程序的任何错误信息送到文件err.file中,以备将来检查用。


还可以使用另一个输出重定向操作符(&>;)将标准输出和错误输出同时送到同一文件中。例如:


$ ls /usr/tmp &> output.file


利用重定向将命令组合在一起,可实现系统单个命令不能提供的新功能。例如使用下面的命令序列:


$ ls /usr/bin > /tmp/dir

$ wc –w < /tmp/dir

459


统计了/usr/bin目录下的文件个数。


4、管道


将一个程序或命令的输出作为另一个程序或命令的输入,有两种方法,一种是通过一个临时文件将两个命令或程序结合在一起,例如上个例子中的/tmp/dir文件将ls和wc命令联在一起;另一种是Linux所提供的管道功能。这种方法比前一种方法更好。


管道可以把一系列命令连接起来,这意味着第一个命令的输出会作为第二个命令的输入通过管道传给第二个命令,第二个命令的输出又会作为第三个命令的输入,以此类推。显示在屏幕上的是管道行中最后一个命令的输出(如果命令行中未使用输出重定向)。


通过使用管道符“|”来建立一个管道行。用管道重写上面的例子:


$ ls /usr/bin|wc -w

1789


再如:


$ cat sample.txt|grep "High"|wc -l


管道将cat命令(列出一个文件的内容)的输出送给grep命令。grep命令在输入里查找单词High,grep命令的输出则是所有包含单词High的行,这个输出又被送给wc命令,wc命令统计出输入中的行数。假设sample.txt文件的内容如下:


Things to do today:

Low:Go grocery shopping

High:Return movie

High:Clear level 3 in Alien vs. Predator

Medium:Pick up clothes from dry cleaner


那么该管道行的结果是2。


5、命令替换


命令替换和重定向有些相似,但区别在于命令替换是将一个命令的输出作为另外一个命令的参数。常用命令格式为:


command1 `command2`


其中,command2的输出将作为command1的参数。需要注意的是这里的`符号,被它括起来的内容将作为命令执行,执行后的结果作为command1的参数。例如:


$ cd `pwd`


该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下。


五、linux shell 函数


在shell中可以定义函数。函数实际上也是由若干条shell命令组成的,因此它与shell程序形式上是相似的,不同的是它不是一个单独的进程,而是shell程序的一部分。函数由两部分组成:函数名和函数体。


n函数定义的格式为:


函数名()

{

命令集合

}

n或者

function 函数名()

{

命令集合

}


Shell函数与脚本的区别


Shell函数和shell程序比较相似,它们的区别在于:


Shell程序在子Shell中运行,而Shell函数在当前Shell中运行。因此在当前Shell中可以看到Shell函数对变量的修改。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存