Unix Shell 学习笔记【2】

第六学时:进程

在 Unix下,每个程序作为一个进程运行。在 Unix中无论何时执行一行个命令,它都创建或启动一个新进程。操作系统使用一个叫做 pid或进程 ID的 5位数字 ID来跟踪进程。系统中每个进程都有一个唯一的 pid。在任何时刻,系统中都没有两个有相同 pid的进程,因为 pid是 Unix用来跟踪每个进程的。用户可以用 ps命令查看当前正在运行什么进程和系统中的所有进程。当用户启动一个进程 (运行一条命令 )时,有两种运行方式 -前台或后台。它们的区别是进程在终端怎样与用户交互。

1.      前台进程: 缺省下,用户启动的每个进程都在前台运行,进程从键盘得到输入并把输出送到屏幕上。用户虽然可以重定向进程的输入和输出,但缺省情况下输入输出与用户的终端相连接。进程在前台运行,输出被定向到屏幕。

2.      后台进程: 一个后台进程运行时不必与键盘连接。如果后台进程要求键盘输入,则进行等待。在后台运行一个进程的优点是用户可以运行其他命令,用户不需要等待一个进程完成再启动另一个。启动一个后台进程最简单的方式是在命令的后面添加一个 & 符号!

显示正在运行的所有进程的命令: ps (process status)

 

 

第二部分    Shell 编程

变量的定义方法: name=value   其中 name是变量名, value是该变量所保持的值。

变量名只能以字母或下划线开头。以数字开头的变量名将保留为 Shell使用,用户可以使用存储在这些变量中的值,但不能自己设置。在变量中不能使用如 ”!,*,-”这些字符,因为这些字符对 Shell而言有特殊的意义。变量值: Shell使程序员可存储任何想让变量存储的值。如 FRUIT=peach;FRUIT=2apples;FRUIT=apple+pear+kiwi;

需要注意的是在使用带空格的值时,需要引用改值: FRUIT=”apple orange plum”

访问值:为访问存储在变量中的值,只要在其变量名之前加上美元符号 ”$”即可。例如命令: $echo $FRUIT

                    peach

显示出变量 FRUIT所存储的值,本例中为 ”peach”。若没有使用美元符号 ”$”访问变量的值,则打印出变量的名字而不是它的值,如: $echo FRUIT        FUIRT

只是简单地打印出 FRUIT,并不打印变量 FRUIT的值。注意美元符号 ”$” 只能用来访问变量的值,而不能用于定义变量!!牢记,当美元符号 ”$” 在一个变量名之前时,用该变量的值替换该变量!!

数组提供了一种将变量集合分组的方法。程序员不是为每个所要求的变量创建一个新名字,而是使用一个数组变量存储所有其他变量。创建数组变量的最简单方法就是为数组中的每一个元素赋值,表达式如下:

name[index]=value,这里 name为数组名, index是数组中程序员想设置的下标, value是想为该项赋的值。例如,下列命令:

$FRUIT[0]=apple

$FRUIT[1]=banana

$FRUIT[2]=orange

也可以不按照顺序赋值,如 $FRUIT[10]=plum   需要注意的是 Shell并不为下标 2~10之间的一串空白数组项用空格填满,相反, Shell只跟踪那些附了值的数组元素。

若定义的数组变量与某个已定义的标量同名,则标量值为数组下标为 0 的那个元素的值。如,若执行如下命令:

$FRUIT=apple

$FRUIT[1]=peach

元素 FRUIT 中有值 apple 。运行到这里,任何对标量 FRUIT 的访问都被看成对项 FRUIT[0] 的访问。

数组初始化的第二种方式是一次设置多个元素: name=(value1,…,valuen)

这里, name是数组名; value,从 1~n,是准备赋给每一项的值,从 0开始的连续数组下标。如 :$band=(derri terry mike gene),它等价于如下命令:

$band[0]=derri

$band[1]=terry

$band[2]=mike

$band[3]=gene

访问数组值:

在为数组赋值后,可对它们进行访问:

${name[index]}

这里 name为数组名, index是欲访问元素的下标。可使用如下方式访问数组中的所有项:   ${name[*]}   ${name[@]}

若数组中某一项所存储的值带有空格,则这种格式的数组访问方法就不能正常工作了,这时就需要使用第二种格式。第二种格式用引号引住所有数组项,这样嵌入的空格就保留了下来。

只读变量:通过使用 readonly命令, Shell提供了一种将变量标记为只读的方式,当命令被标记为只读时,它的值不可改变。

$fruit=kiwi

$readonly fruit

$echo $fruit

Kiwi

$fruit=cantaloupe

//errir message…….

删除变量:删除 (Unsetting) 变量告诉 Shell 从其跟踪的变量清单中移走该变量,这类似于要求 Shell 忘掉一块不常用的信息。标量和数组变量都可以通过使用 unset 命令进行删除。不能使用 unset 命令删除被标识为只读的变量。

 

环境变量: 当 Shell在运行时,存在三种主要变量:局部变量,环境变量, Shell变量。

局部变量 (local variable) 是只在当前 Shell实例中存在的变量,而由其他 Shell启动的程序不能使用该变量。前面所提到的变量都是局部变量。

环境变量 (environment variable) 是 Shell的任何子进程都能使用的变量,许多程序要正确运行都需要使用环境变量。通常 Shell脚本只定义程序运行时所需要的环境变量。

Shell 变量 (Shell variable) 是 Shell设置的特殊变量,是 Shell在初始化和使用过程中设置的变量,用户可以改变这些变量的值。也是 Shell正确运行所必须的,这些变量有些是环境变量而有些是局部变量。

                                   

                                    比较局部、环境、 Shell变量

 

属性

局部变量

环境变量

Shell变量

可被子进程访问

No

Yes

Yes

由用户设置

Yes

Yes

No

由 Shell设置

No

No

Yes

用户可更改

Yes

Yes

No

Shell要求使用

No

No

Yes

 

我们在 Linux下安装系统软件的时候 ,经常遇到一些系统环境变量配置的问题。什么是环境变量?如何定制环境变量?我将在下面做一些介绍。
一、 什么是环境变量?
Linux 是一个多用户的操作系统。多用户意味着每个用户登录系统后,都有自己专用的运行环境。而这个环境是由一组变量所定义 , 这组变量被称为环境变量。用户可以对自己的环境变量进行修改以达到对环境的要求。
二、定制环境变量  
环境变量是和 Shell紧密相关的,它是通过 Shell命令来设置的。环境变量又可以被所有当前用户所运行的程序所使用。对于 bash来说,可以通过变量名来访问相应的环境变量。
下 面通过几个实例来说明
1. 显示环境变量 HOME 
$ echo $HOME
/home/admin
2. 设置一个新的环境变量 NAME
$ export NAME=" RaidCheng"
$ echo $NAME
RaidCheng
3. 使用 env 命令显示所有的环境变量  
$ env
HOSTNAME=test
TERM=vt100
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=202.xxx.xxx.xxx 53694 22
CATALINA_BASE=/usr/local/jakarta-tomcat
SSH_TTY=/dev/pts/0
ANT_HOME=/usr/local/ant
JAVA_OPTS=-server
USER=admin
...
4. 使用 set 命令显示所有本地定义的 Shell 变量  
$ set
BASH=/bin/bash
BASH_VERSINFO=([0]=" 2"  [1]=" 05b"  [2]=" 0"  [3]=" 1"  [4]=" release"  [5]=" i386-redhat-linux-gnu" )
BASH_VERSION=' 2.05b.0(1)-release'
CATALINA_BASE=/usr/local/jakarta-tomcat
CATALINA_HOME=/usr/local/jakarta-tomcat
...
5. 使用 unset 命令来清除环境变量  
$ export NAME=" RaidCheng"
$ echo $NAME
RaidCheng
$ unset NAME
$ echo $NAME
6. 使用 readonly 命令设置只读变量  
$ export NAME=" RaidCheng"
$ readonly NAME
$ unset NAME
-bash: unset: NAME: cannot unset: readonly variable
$ NAME=" New"  # 会发现此也变量不能被修改
-bash: TEST: readonly variable
三、常见的环境变量  
PATH
      决定了 shell 将到哪些目录中寻找命令或程序
HOME
      当前用户主目录
HISTSIZE
    历史记录数
LOGNAME 
    当前用户的登录名  
HOSTNAME
    指主机的名称
SHELL 
     前用户 Shell 类型  
LANGUGE 
    语言相关的环境变量,多语言可以修改此环境变量
MAIL
      当前用户的邮件存放目录  
PS1
         基本提示符, 对于 root 用户是 # ,对于普通用户是 $
PS2
         附属提示符,默认是 “>”
四、通过 C 程序来访问和设置环境变  

对于 C程序的用户来说,可以使用下列三个函数来设置或访问一个环境变量。  
getenv()访问一个环境变量。输入参数是需 要访问的变量名字,返回值是一个字符串。如果所访问的环境变量不存在,则会返回 NULL
setenv()在程序里面设置某个环境变量的函 数
unsetenv()清除某个特定的环境变量的函数
另外,还有一个指针变量 environ,它指向的是包含所有的环境 变量的一个列表。下面的程序可以打印出当前运行环境里面的所有环境变量:
#include 
extern char**environ;
int main ()
{
char**var;
for (var =environ;*var !=NULL;++var)
printf (" %s /n " ,*var);
return 0;
}
五、 环境变量文件
通过修改一些相关的环境定义文件来修改环境变量,比如对于 RedHat,与环境相关的文件有 /etc/profile和 ~ /.bash_profile等。修改完毕后重新登录一次或运行命令 source xxx就生效了。  

标量 (scalar variable):标量一次只能存放一个值。

 

第八学时   替换

当遇到包含一个或更多特殊字符的表达式时, Shell执行替换。使用特殊字符 $访问变量的值,就是替换。检索变量值的过程称为变量替换 (variable substitution),除了这种类型的替换, Shell可以执行几种其他类型的替换:

文件替换 (称为 globbing)。

基于值的变量替换。

命令替换。

算术替换。

1. 文件名替换: 最常见通用的替换类型是文件名替换,有时也称为 globbing.文件名替换时 Shell用于将一包含通配符的字符串扩展成一个文件清单的过程。

                                    用于文件名替换的通配符

通配符

描述

*

匹配零个或多个存在的任何字符

?

匹配一个存在的任何字符

[characters]

匹配任何给出字符 characters 之一

 

1) 使用 *通配符:文件名替换最简单的格式是 ”*”字符。 ”*”告诉 Shell匹配零个或多个存在的字符,若只给出 *号,则匹配所有的文件。如: $ls *   列出当前目录中的每个文件和每个目录。在许多情况下要求只使用 *字符,不过,它的强大之处在于可以使用它匹配文件前缀、后缀或者同时匹配前缀和后缀。 (a) 匹配文件前缀: command prefix*;command是命令名,如 ls; prefix是欲匹配的文件名前缀。 (b) 匹配文件后缀: command *suffix; 如 $ls *doc (c)匹配后缀和前缀: command profix*suffix    $ls backup*doc   or    $ls CGI*st*java (匹配以字符串 CGI开头,以 java结尾且包含字符串 st的文件。 )   需要注意的是使用 * 通配符时,默认情况下是大小写敏感的,因此,前后缀的大小写指定正确是很重要的,如命令 $ls ch1*   会产生如下文件清单: ch10-01 ch10-02 …..

而命令 $ls CH1* 并不会产生相同的文件清单。

2) 使用?通配符:通配符 *的一个限制是,它每次匹配一个或多个字符。但是假设用户想列出所有文件名格式为 ch0x.doc的文件,这里 x 是单个数字或字母 。此时,就要使用通配符?。为了只匹配一个字符, Shell提供了通配符?,可使用该通配符重写命令: $ls ch0?.doc  

3) 匹配字符集:通配符 *和?的两个潜在的问题是    (a) 它们匹配所有的字符,包括特殊字符如连字符 -或下划线 _.(b) 当只想匹配字母或只想匹配数字时非常困难。

有时候要对想要匹配的确切字母做更多的控制,考虑这样一种情况:用户想要匹配的文件其文件名格式为 ch0X,这里 X为一个从 0-9的数字,这时 *和?都不能完成该工作。幸运的是, Shell提供了使用 []通配符匹配字符集的能力,使用该通配符的语法如下: command[characters],这里 command是命令名,如 ls;characters代表想匹配的字符集,如下列命令完成了前面的要求:   $ls ch0[0123456789].doc  or $ls ch0[0-9].doc

例子:匹配所有以字母开头的文件: $ls [a-z A-Z]*

            匹配所有以字母或数字结尾的文件: $ls *[a-z A-Z 0-9]

否定一个集合:

用户需要除包含字母 a的文件外的所有文件的清单,可以有两种方法来解决这个问题。 1) 指出想要文件名包含的所有字符 2) 指出不应包含字母 a的文件名。

通常采用第二种方法,通配符 []提供了匹配除在集合中指定字符外的所有字符的能力,这称为否定集。用户可通过指定!操作作为集合的第一个字符完成该任务。语法格式为: command [!characters]  这里, command是命令名,如 ls; characters是不想匹配的字符集。如,列出所有除以 a字符开头的所有文件,可以使用命令:

$ls [!a]*

2. 变量替换:

变量替换使得 Shell程序员可以基于变量的状态来操纵变量的值,变量替换有两类:   a)  变量有值时动作发生 b)变量无值时动作发生;变量替换动作的范围很大,从进行一次值替换到异常中止脚本。这些动作的类型可以按变量替换的格式分为四种。对于有些必须要写成 if-then-else格式的语句,可以使用变量替换将它们写成缩写格式。

                                                             变量替换

                  格式

                             描述

${parameter:-word}

parameter 为空或未设置,则用 word 代替 parameter 进行替换, parameter 的值不变。

${parameter:=word}

parameter 为空或未设置,则 parameter 设为值 word

${parameter:?message}

parameter 为空或未设置,则 message 作为标准错误打印出来,这可用来检查变量是否正确设置

${parameter:+word}

parameter 设置了,则用 word 代替 parameter 进行替换, parameter 的值不变

           

替换缺省值:第一种格式在变量未被设置或为空时,替换缺省值,正式的描述为: ${parameter:-word}

这里 parameter为变量名, word为缺省值。例子:

PSI=${parameter:-localhost} “$”; export PSI;

可以将它用在用户的 .profile文件以确保提示符正确设置,这种格式的变量替换不影响变量的值,它只当变量为设置时执行替换。

            赋予一个缺省值:要为变量赋值,就要用到第二种格式的变量替换,这种格式正式的描述为: ${parameter:=word}

这里, parameter是变量名, word是将为该变量所设的缺省值 (如果该变量被删除了的话 )。设有命令: PSI=${HOST:= ‘uname -n’}; export PSI HOST;

在执行完该语句后, HOST和 PSI都被赋值。该例也验证了这样一个事实:所使用的缺省字符串不一定是一个固定的字符串,它也可以是一个命令的输出结果。若该替换在 Shell中不存在,与其功能相同的语句应写为:

If [-z “$HOST”];then HOST= ‘uname -n’;fi;PSI=”$HOST$”; export PSI HOST;

显然,变量替换格式比明确格式要简短清晰一些。

            由于变量错误而导致中止:有时,替换缺省值会隐藏一些问题,不过, sh支持第三种格式的变量替换,它使得当变量被删除时向标准错误输出写一条信息。该格式的正式描述为: ${parameter:?message}  该格式常用于 Shell脚本以及 Shell函数中 (为正确执行,该函数要求其内的变量已被设置 )。例如,若变量 $HOME未设置或被删除,下面这条命令将退出:

:${HOME:? “Your home directory is undefined.”} 

最后一种变量替换格式用于当变量已赋值时的替换:格式为: ${parameter:+word} 这里 parameter为变量名, word是当变量已设置时将替换的值,这种格式并不改变变量的值,它只改变它所替换的值。例如,一个常用于表明脚本运行于跟踪调试模式的命令是: echo ${DEBUG:+ “Debug is active.”}

3.      命令和算术替换:

Shell提供的另外两种替换是:命令替换 (command substitution) 使得可以捕获一个命令的输出而在另一个命令中替换它。算术替换 (arithmetic substitution) 使得可以使用 Shell执行一些简单的整数计算。

命令替换 常用于将一个命令的输出赋予一个变量,下面的每个例子都示范了命令替换。注意:命令替换使用的是后引号“ `” .

DATE=`date`   (date命令的输出作为变量 DATE的值 )

USERS=`who | wc `  (管道的输出作为变量 USERS的值 )

算术替换, Shell可执行整数算术运算,当给出如下命令格式时执行算术运算:

$((expression)) expression的计算是根据标注算术管理进行的,下标给出了可以使用的操作符,操作符按优先级列出:

                                            算术替换操作符

 

操作符

描述

      /

除操作符,两个数相除返回结果

      *

乘操作符,两个数相乘返回结果

      -

减操作符,两个数相减返回结果

      +

加操作符,两个数相加返回结果

      ()

括号内的表达式应在其他运算前运算

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值