阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

shell编程培训之shell的工作原理

155次阅读
没有评论

共计 8058 个字符,预计需要花费 21 分钟才能阅读完成。

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 和移动命令 rm,是存在于文件系统中某个目录下的单独的程序。对用户而言,不必关心一个命令是建立在 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 是如何工作的。

$makework

make:***Noruletomaketarget‘work’.Stop.

$

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

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

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

$myprog

bash:myprog:commandnotfound

$

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

Shell 的种类

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

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

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

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

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

#fgreplisa/etc/passwd

lisa:x:500:500:TurboLinuxUser:/home/lisa:/bin/bash

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

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

shell 命令

命令行 c

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

$date

二 112301:34:58CST1999

$

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

$CommandOptionArguments

1. 选项和参数

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

$ls

motdpasswd

$

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

$ls-l

total2

-rw-r–r–2wzhbook22Apr2020:37motd

-rw-r–r–2wzhbook796Apr2020:37passwd

$

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

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

$ls-ltext

-rw-r–r–2wzhbook22Apr2020:37motd

-rw-r–r–2wzhbook796Apr2020:37passwd

$

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

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

$cp-imydatanewdata

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

2. 命令行特征

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

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

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

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

$ls-F;cp-imydatanewdata

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

$cp–i

mydata

newdata

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

Shell 中的特殊字符

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

1. 通配符

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

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

? 代表任何单个字符。

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

下面我们给出表 10- 1 说明这些通配符的具体含义。

表 10-1 通配符含义举例

模式串

意义

*

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

*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 将使用此模式串本身作为参数传给有关命令。这可能就是命令中出现特殊字符的原因所在。

2. 引号

在 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=”currentdirectoryis`pwd`”

$echo$string

currentdirectouris/home/xyz

$

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

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

$today=`date`

$echoTodayis$today

TodayisMonApr1516:20:13CST1999

$

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

$abc=`echoThenumberofusersis`who|wc-l“

$echo$abc

Thenumberofusersis5

$

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

$ls

notereadme.txtNoticeUnix.dir

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

$echo$TestString

/home/yxznoteNotice

$

其他情况,读者可自行试之。

1. 注释符

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

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

标准输入 / 输出和重定向

1. 标准输入与输出

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

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

$catconfig

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

$cat

Helloworld

Helloworld

Bye

Bye

$

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

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

$sort

bananas

carrots

apples

apples

bananas

carrots

$

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

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

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

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

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

2. 输入重定向

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

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

$wc

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

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

$wc/etc/passwd

2023726/etc/passwd

$

另一种把 /etc/passwd 文件内容传给 wc 命令的方法是重定向 wc 的输入。输入重定向的一般形式为:命令 thistextformsthecontent

>oftheheredocument,which

>continuesuntiltheendof

>textdelimter

>delim

41798

在文件名。例如:

$ls>directory.out

$catdirectory.out

ch1.docch2.docch3.docchimpconfigmail/test/

$

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

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

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

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

$ls*.doc>>directory.out

$catdirectory.out

ch1.docch2.docch3.docchimpconfigmail/test/

ch1.docch2.docch3.doc

$

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

$ls/usr/tmp2>err.file

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

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

$ls/usr/tmp&>output.file

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

$ls/usr/bin>/tmp/dir

$wc–w

想必各位看了这篇文章之后一定会有所收货,若想了解更多相关知识请继续锁定马哥教育!

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-12-03发表,共计8058字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中