打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
引用 第7讲 Bourne Again Shell_1
第7讲 Bourne Again Shell_1
Chatper 8 Bourne Again Shell
此讲和下一讲内容如下:
进一步讨论了shell的交互特性
讨论了简单shell脚本的创建和运行
进一步讨论了作业控制
介绍shell编程的基本方面
讨论命令历史和别名
讨论了命令行扩展
8.2 shell基础
?8.2.1初始化文件
Shell启动时,运行初始化文件初始化自己。登录shell、非登录交互式shell(比如通过命令bash)与非交互式shell(用来执行shell脚本)具体运行的初始化文件各不同。
这里讨论的是bash
?1.登录shell (包括带—login的shell执行)
/etc/profile:首先执行的文件
~/.bash_profile、~/.bash_login、~/.profile  :依次找,执行三个中第一个找到的
?2.交互式非登录shell
~/.bashrc:执行此文件
/etc/bashrc:许多~/.bashrc调用此文件
说明:交互式非登录shell从登录shell继承了由初始化文件设置的shell变量。
?3.非交互式shell
非交互式shell从登录shell那里继承了由初始化文件设置的shell变量。
BASH_ENV  非交互式shell查找环境变量BASH_ENV(或者当作为sh调用时为ENV),并执行由该变量命名的文件中的命令。
?4.建立初始化文件
用户通常只需要主目录下的.bash_profile和.bashrc文件
因为.bashrc中的命令可能执行多次,并且因为子shell继承那些被输出的变量,所以最好将那些附加已有变量的命令放置到.bash_profile文件中。如:
PATH=$PATH:$HOME/bin
此命令将home目录的子目录bin添加到PATH中,应该将其放置到.bash_profile文件中
?5. “.”(句点)或者source
这两个命令在当前shell中运行初始化文件,从而使修改生效
$ ~/.bashrc
?8.2.2符号命令
符   号
命    令
( )
子shell
$( )
命令替换
(( ))
算术表达式计算,let的同义词(当被括起来的值中包含等号时使用)
$(( ))
算术扩展(不用于被括起来的值中包含等号的情形)
[ ]
test命令
{ }
条件表达式,类似于[ ],但添加了字符串比较
?8.2.3  重定向标准错误输出
文件描述符  文件描述符是程序发送输出和获取输入的地方。当执行一个程序时,运行该程序的进程打开了3个文件描述符,分别是:0(标准输入)、1(标准输出)和2(标准错误输出)。重定向输出符号(>)是1>的简写,它通知shell重定向标准输出。类似地,<是0<的简写,表示重定向标准输入。符号2>将重定向标准错误输出。
将标准输出和标准错误输出重定向到不同文件的例子
$ cat x y 1> holdl 2> ho1d2
$ cat holdl
This "is y.
$ cat ho1d2
cat: x: No such file or directory
?8.2.4  编写一个简单的shell脚本
shell脚本是包含shell可执行命令的文件。
shell脚本中的命令可以是用户在shell提示符后面输入的任何命令
除了可以使用用户在命令行下面输入的命令之外,shell脚本还可以使用控制流命令(也称为控制结构)。
shell一条接着一条地解释并执行shell脚本中的命令。
脚本文件可以使用任何编辑器编辑。
?1. chmod :使文件可执行
要想用shell脚本的文件名作为命令执行该脚本,用户必须具有该脚本的文件读权限和执行权限
当使用编辑器创建shell脚本的时候,该文件通常并没有设置执行权限。
示例给出了一个名为whoson的文件,其中包含shell脚本:
$ cat whoson
date
echo "Users Currently Logged In"
who
$ whoson
bash: ./whoson: Permission denied
执行没有执行权限(但有读权限)的shell脚本
$ bash whoson       #这里whoson是bash的参数
给脚本文件赋执行权限:
Chmod u+x whoson
如果某文件是一个shell脚本,用户尝试执行这个文件时,还必须具备读访问权限。而在执行一个二进制可执行文件(已编译程序)时,并不需要读访问权限。
?#!指定shell
在shell脚本文件的第1行可以放置一行特殊的字符串,告诉操作系统使用哪个shell来执行这个文件。
$ cat bash_script
#! /bin/bash
echo "This is a Bourne Again Shell script. "
$ cat tcsh_script
#! /bin/tcsh
echo "This is a tcsh script. "
set person = jenny
echo "person is $person"
上例中,不管用户当前运行的shell,此脚本都有tcsh执行
如果在#!后面没有可执行程序名,shell将报告一个错误,通知没有找到用户要求运行的命令。
?3. #开始一行注释
使用注释可使shell脚本和程序便于自己和他人阅读和维护。Bourne Again shell和TC Shell的注释语法相同。
?4. 执行shell脚本
直接输入文件名
作为bash的参数
?8.2.5  命令分隔和命令分组
当用户交互地向shell输入命令时,或者在编写shell脚本时,必须分隔不同的命令
?1. 使用;和换行符分隔命令
换行符是一个独特的命令分隔符,它将启动命令执行。
分号;也是一种命令分隔符,但是它并不立即启动命令执
$ x ; y ; z
?2. \继续命令
当输入一个比较长的命令行时,光标已经到达屏幕右端,这时候可以使用反斜杠字符\在下一行继续这条命令。反斜杠引用了换行符(也就是将其转义),这样shell就不会将这个换行符作为一个命令终结符对待。
?3. |和&分隔命令及其他功能
管道符号|和后台任务符号&也是命令分隔符。它们并不开始执行命令而是在某些方面改变命令的功能。
下一个命令行在后台执行任务d和e,而在前台执行任务f:
$ d & e & f
[1] 14271
[2] 14272
shell会将通过管道连接的多个命令当作一个单独的作业。
?4. ( )命令分组
可以使用圆括号进行命令分组。shell为每个命令组创建一个自身的副本,称为子shell。
每个子shell(作业)有各自的运行环境,这就意味着它们各自都有自己的一组与其他子shell不同值的变量。
$ (a ; b) & c &
[1] 15520
[2] 15521
上例中,任务a和b相继启动,c同时启动
$ (a ; b) & (c ; d) &
下面的脚本cpdir将复制一个目录到另一个目录中。第2对圆括号将创建一个子shell来运行管道后面的命令。因为这些圆括号,第1个tar命令的输出可用于第2个tar命令,而不管中间的cd命令。如果没有圆括号,第1个tar命令的输出将会发送给cd,然后被丢弃,这是因为cd并不处理来自标准输入的输入数据。如果没有这对圆括号,第1个cd命令将改变该脚本的工作目录(同时还会导致第2个cd命令的工作目录改变)。
$ cat cpdir
(cd $1 ; tar -cf - . ) | (cd $2 ; tar -xvf - )
$ cpdir /home/alex/sources /home/alex/memo/bibtio
?8.2.6  作业控制
下面的命令行中包含了两个指定在后台运行的任务:
$ find . -print | sort | lpr & grep -1 alex /
tmp/* >alexfiles &
[1] 18839
[2] 18876
?1. jobs:列出作业
?2. fg或%:将作业移到前台运行
?3. bg:将作业移到后台运行
后台作业要从终端进行读取操作时,shell将停止该作业,并通知用户该作业已被停止并等待输入。
?8.2.7  操作目录栈
Bourne Again和TC Shell都允许用户将其正在使用的目录列表存放起来,这样就可以在这些目录之间轻易移动。这个目录列表称为栈。
?1. dirs:显示栈
dirs显示目录栈,为空则显示工作目录的名字。
$ dirs
~/literature
下面的讨论基于下图的目录结构
?2. pushd(push directory ):将目录压入栈顶
pushd改变工作目录,添加一个新的目录到栈顶。
$ pushd ../demo
~/demo ~/literature
$ pwd
/home/sam/demo
$ pushd ../names
~/names ~/demo ~/literature
$ pwd
/home/sam/names
当不带参数使用pushd时,pushd交换栈顶最上面的两个目录并将新的栈顶目录作为新的工作目录
不管是否显式地创建目录栈,都可以使用cd– 切换到前一个目录。为了访问目录栈中的其他目录,可以在调用pushd时,带上一个以加号开头的数字作为参数。栈中目录的编号从栈顶开始算起,栈顶目录的编号是0。
下面的pushd命令继续前一个示例
$ pushd +2
~/literature ~/demo ~/names
$ pwd
/home/sam/literature
?3. popd(pop directory ):将目录从栈中弹出
不带参数的popd将栈顶目录从栈中移出,并将工作目录改变到这个新的栈顶目录。
$ dirs
~/literature ~/demo ~/names
$ popd
~/demo ~/names
$ pwd
/home/sam/demo
为了移出除栈顶之外的其他目录,可以使用一个以加号开头的数字作为参数传递给popd。
$ dirs
~/literature ~/demo ~/names
$ popd +1
~/literature ~/names
移出标号不为0的目录并不会改变工作目录。
?8.3  参数和变量:变量在引用时一般在前面加$
在shell中,shell参数与用户可访问的某个值相关。参数的名字由字母、数字和下划线组成,常被称为shell变量,或者简称为变量。
变量名必须以字母或者下划线开头,而不能是数字。
用户命名并赋值的shell变量称为用户创建的变量。可以将用户创建的变量变成全局变量。全局变量(又称为环境变量)可以被任何shell和从最初shell创建的其他程序访问。
这里有一个命名约定,即全局变量只使用大写字母,而其他变量则使用大小写混合命名。
$ myvar = abc       #怎样声明没初始值的变量
Bourne Again Shell允许在命令行中放置变量赋值语句。这些赋值语句只是该命令shell的局部行为,也就是说它们只适用于该命令。
$ cat my_script
echo $TEMPDIR
$ TEMPDIR=/home/sam/temp my_script
/home/sam/temp
$ echo $TEMPDIR
$
关键字shell变量(简称为关键字变量)对于shell而言,具有特殊的意义,它们的名字一般比较短而且有助于记忆。 Shell启动时,将从环境中继承几个关键字变量。HOME和PATH就属于这样的变量。
一行命令中的每个参数都将成为位置参数的值。使用位置参数可以访问命令行参数。内置命令set可以用来对位置参数赋值。
其他经常需要用到的shell脚本值,比如最后一次执行的命令名、命令行参数的个数以及最近执行命令的状态等,这些值均保存在特殊参数中。用户不能对特殊参数赋值。
?8.3.1  用户创建的变量
–$ person=alex
$ echo person
person
$ echo $person
alex
由于开头的$,shell识别出这是一个变量的名字,并将该变量的值代入,同时将该值传递给echo。Echo显示变量的值而不是它的名字
当使用变量作为参数执行一个命令的时候,shell将用该变量的值来代替变量名,并将该值传递给正在执行的程序。如果变量的值包含特殊字符,比如*或者?,shell可能还会扩展这个变量。
在下面的命令序列中,第1行命令将字符串alex*赋值给变量memo。Bourne Again Shell在向变量赋值的时候,bash并没有进行路径名扩展。在下面的echo命令行中,双引号将$memo的展开值中的星号(*)引起来,这样在将其值传递给echo命令之前,可以阻止bash对已展开的变量memo进行路径名展开:
$ memo=a1ex*
$ echo "$memo"
alex*
当引用一个包含未被引号引起来的特殊字符的变量时,所有shell均将这些字符解释为特殊字符。
$ ls
alex.report
a1ex.summary
$ echo $memo
alex.report alex.summary
语法$VARIABLE是${ VARIABLE }的特殊情形,后者要更加通用,它将变量名用${}括起来。花括号将变量名隔离开。将一个变量和一个字符串连接起来的时候,花括号是必要的:
$ PREF=counter
$ WAY=$PREFc1ockwise
$ FAKE=$PREFfeit
$ echo $WAY $FAKE
$
shell认为一个未设定值的变量为空字符串(null),为了实现这些语句的意图,需要使用花括号来引用PREF变量:
$ PREF=counter
$ WAY=${PREF}c1ockwise
$ FAKE=${PREF}feit
$ echo $WAY $FAKE
counterclockwise counterfeit
Bourne Again Shell通过位置参数如$1, … $9,引用命令行中的参数。引用第9个之后的参数,就必须使用花括号:${10}。命令的名字保存在$0中。
unset:删除变量。除非变量被删除,否则它将伴随着创建它的shell一直存在。使用值null(在tcsh中,使用set person =)可以将变量的值删除,但是不删除该变量:
$ person=
$ echo $person
$
$ unset person
?8.3.2  变量属性
?1. readonly:使变量值不可变更
如果尝试删除或者改变只读变量的值,shell将显示一条错误消息:
$ person=jenny
$ echo $person
jenny
$ readonly person
$ person=he1en
bash: person: readonly variable
当不带参数使用内置命令readonly时,它会列表显示所有只读变量。
?2. declare和typeset:为变量赋值与属性
内置命令declare和typeset可用来设置shell变量的属性和值。
?表8-3  变量属性(typeset或者declare)
属性
含义
-a
声明一个数组变量
-f
声明一个函数变量
-i
声明一个整数变量
-r
声明变量为只读,可用readonly
-x
输出变量(设置为全局变量),也可用export
下面的命令声明了几个变量并设置了一些属性。第1行声明可以不带字declare。
$ declare personl=a1ex
$ declare -r person2=jenny
$ declare -rx person3=he1en
$ declare -x person4
可以以任意顺序分别列出declare的选项。
$ declare -x -r person3=helen
将clare命令行中的连字符换成字符+,可以为变量删除某个属性。用户不能删除只读属性。怎样删除只读属性
$ declare +x person3      #person3不再为全局变量
可以用typeset代替declare
不带任何参数和选项,命令declare将列出所有shell变量。
declare带有选项,但是没有变量名作为参数,那么,将列出所有具有指定属性集合的shell变量。
默认情况下,变量的值作为字符串存放。当对某个字符串变量进行算术运算的时候,shell将该变量转换为一个数字,计算完之后,再将其转换为字符串。具有整数属性的变量将作为整数存放。下面将为变量指派整数属性:
$ typeset -i COUNT
?8.3.3  关键字变量
关键字变量可以通过继承而来,也可以在shell启动时声明并初始化。可通过命令行方式或者在初始化文件中为这些变量指派值。
?1. HOME:用户的主目录
shell使用HOME的值来展开路径名,该路径名使用简写形式(代字号~)来表示用户的主目录。
?2. PATH:shell查找程序的路径
变量PATH按照顺序指定了shell应该搜索的目录。每个目录彼此之间必须使用冒号隔开。下面的命令设置PATH,最后,shell将在工作目录中搜索。输出PATH将使其值可以被子shell访问:
$ export PATH=/usr/1oca1/bin:/bin:/usr/bin:~/bin:
该串中的空值表示工作目录 (该串的最后一个元素 )
一般而言,超级用户的PATH要完全忽略工作目录。将工作目录放在PATH的首位会导致安全黑洞。可在设置PATH新值时引用旧值
?4. PS1:用户主提示符
变量PS1(在tcsh下是prompt)保存了shell用来提示用户输入命令的提示符串。当用户修改PS1或者prompt的值时,用户的提示符就会发生改变。
$ PSl="[\u@\h \W \!]$ "
[user@host directory event]$
?5. PS2:用户次提示符—等待完成输入的提示符
?6. PS3:菜单提示符
PS3保存了用于select控制结构的菜单提示符。
?7. PS4:调试提示符
PS4保存了bash调试提示符。
?8. IFS:分隔输入字段(分词)
IFS(Internal Field Separator,内部字段分隔符)shell变量(tcsh没有)指定了在命令行中用来分隔参数的字符,其默认值为空格符、制表符和换行符。
当为IFS指派字符值的时候,这些字符也可以分隔字段,但是只有在进行展开的时候才可以这样。
$ IFS="p"
$ export VAR
尽管IFS设置为p,但是在export命令行中的p并没有展开,因此字export并没有分词。
?9. CDPATH:扩大cd的范围
使用CDPATH变量(在tcsh下为cdpath),用户可以用一个简单的文件名作为参数传递给内置命令cd,就将工作目录改变到某个目录,而这个目录并不是工作目录的子目录。
export CDPATH=$HOME:$HOME/literature
此命令使cd搜索用户主目录、目录literature以及输入cd命令时所在的工作目录。
若希望cd首先搜索工作目录(以root身份登录则一定不要这样做,请参见第8.3.3),那么可将空字符串作为CDPATH的第1项。空字符串用两个冒号(::)表示。
export CDPATH=: :$HOME: SHOME/literature
?8.3.4  特殊字符
表8-6 列出了bash 和tcsh shell 的特殊字符。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
主题 109: Shell、脚本、编程和编译
《Linux命令行与shell脚本编程大全》使用其他shell
bash的一些内建命令
第十四章 SHELL 脚本
shell浅谈之一变量和引用
linux-shell脚本基础-2
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服