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的计算是根据标注算术管理进行的,下标给出了可以使用的操作符,操作符按优先级列出:

                                            算术替换操作符

 

操作符

描述

      /

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

      *

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

      -

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

      +

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

      ()

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

 


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值