首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Shel编程惯用

2012-09-11 
Shel编程常用深入浅出Shell编程: Shell 变量 1 系统变量 2 Shell用户变量 2.1 基础 2.2 使用技巧 2.3 shel

Shel编程常用


深入浅出Shell编程: Shell 变量
1 系统变量
2 Shell用户变量
2.1 基础
2.2 使用技巧
2.3 shell 中的数组
3 shell 环境变量
先不要管Shell的版本,来看看Shell 变量,在Shell中有三种变量:系统变量,环境变量,用户变量。其中用户变量在编程过程中使用最多,系统变量在对参数判断和命令返回值判断会使用,环境变量主要是在程序运行的时候需要设置。
1 系统变量
Shell常用的系统变量并不多,但却十分有用,特别是在做一些参数检测的时候。下面是Shell常用的系统变量 表示方法? 描述?
$n? $1 表示第一个参数,$2 表示第二个参数 ...?
$#? 命令行参数的个数(传递到脚本的参数个数)
$0? 当前程序的名称?
$?? 前一个命令或函数的返回码(显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。)
$*? 以"参数1 参数2 ... " 形式保存所有参数(以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个)
$@? 以"参数1" "参数2" ... 形式保存所有参数(与$#相同,但是使用时加引号,并在引号中返回每个参数)
$$? 本程序的(进程ID号)PID(脚本运行的当前进程ID号)
$!? 上一个命令的PID(后台运行的最后一个进程的进程ID号)
$- 显示shell使用的当前选项,与set命令功能相同


其中使用得比较多得是 $n $# $0 $? ,看看下面的例子: BeautifierPlugin Error: Unable to handle "bash" syntax.
#!/bin/sh
#This file is used to explain the shell system variable.
echo "the number of parameter is $# ";
echo "the return code of last command is $?";
echo "the script name is $0 ";
echo "the parameters are $* ";
echo "\$1 = $1 ; \$2 = $2 ";
下面是运行结果:
BeautifierPlugin Error: Unable to handle "bash" syntax.
-bash-2.05b$ ./chapter2.1.sh winter stlchina
the number of parameter is 2
the return code of last command is 0
the script name is ./chapter2.1.sh
the parameters are winter stlchina
$1 = winter ; $2 = stlchina
这个例子太简单了,一点也不实用,下面来个实用的,如果你看不懂,没有关系,后面的内容会有详细解释。 BeautifierPlugin Error: Unable to handle "bash" syntax.
#!/bin/sh
if [ $# -ne 2 ] ; then
echo "Usage: $0 string file";
exit 1;
fi
grep $1 $2 ;
if [ $? -ne 0 ] ; then
echo "Not Found "$1" in $2";
exit 1;
fi
echo "Found "$1" in $2";
上面的例子中使用了$0 $1 $2 $# $? 等变量,下面是程序的解释:
判断运行参数个数,如果不等于2,显示使用"用法帮助", 其中 $0 表示就是脚本自己。
用grep 在$2 文件中查找$1 字符串。
判断前一个命令运行后的返回值(一般成功都会返回0, 失败都会返回非0)。
如果没有成功显示没找到相关信息,否则显示找到了。
其中"表示转义,在"" 里面还需要显示"号,则需要加上转义符" .
下面运行的例子:
BeautifierPlugin Error: Unable to handle "bash" syntax.
./chapter2.2.sh usage chapter2.2.sh
Not Found "usage" in chapter2.2.sh
-bash-2.05b$ ./chapter2.2.sh Usage chapter2.2.sh?????
echo "Usage: $0 string file";
Found "Usage" in chapter2.2.sh
2 Shell用户变量
2.1 基础
不管系统变量有多少,对于需求来说,总是不够的。用户变量是最常用到的变量,使用也十分简单。
用户定义的变量必须由字母数字及下划线组成,并且变量名的第一个字符不能为数字, 与其它UNIX名字一样,变量名是大小写敏感的. 对于用户变量,用户可按如下方式赋值: BeautifierPlugin Error: Unable to handle "bash" syntax.
? name="Winter"
在引用变量时,需在前面加$符号,用户也可以在变量间进行相互赋值,如: BeautifierPlugin Error: Unable to handle "bash" syntax.
? name="Winter"
? WINTER=$name
? echo "Hello $WINTER !"
输出结果应该很清楚:Hello Winter !
这里需要注意一点:变量和'='之间不要有空格,'='和赋值也不要有空格,否则shell不会认为变量被定义。掌握了基本的使用方法,你可以完全开始你的编程工作了。不过有时候需要未雨绸缪,下面介绍用户变量的一些技巧。
2.2 使用技巧
也可以用变量和其他字符组成新的字,这时可能需要把变量用{}括起,如: BeautifierPlugin Error: Unable to handle "bash" syntax.
?SAT=Satur
?echo Today is ${SAT}day
输出结果是: Today is Saturday
有时候为了避免变量名和别的字符产生混淆,你最好养成习惯把变量名用{}括起来。
对于未赋值的变量, Shell以空值对待, 用户也可以用unset命令清除给变量赋的值.看一个例子: BeautifierPlugin Error: Unable to handle "bash" syntax.
#!/bin/sh
echo "a=$a" ;
a=2
echo "a=$a" ;
unset a
echo "a=$a" ;
先猜猜结果是什么? BeautifierPlugin Error: Unable to handle "bash" syntax.
-bash-2.05b$ ./test.sh
a=
a=2
a=
如果你懂C++,你应该知道有个变量修饰符"const",用于避免程序一不小心对变量进行修改。在shell中,对于用户变量,你可以使用同样的修饰符"readonly", 如果我把上面的例子修改成这样: BeautifierPlugin Error: Unable to handle "bash" syntax.
#!/bin/sh
echo "a=$a" ;
#下面增加了readonly
readonly a=2???
echo "a=$a" ;
unset a
echo "a=$a" ;
其结果当然会不一样了: BeautifierPlugin Error: Unable to handle "bash" syntax.
-bash-2.05b$ ./test.sh
a=
a=2
a=2
2.3 shell 中的数组
shell变量中还能设置数组,但是不同的shell版本有不同数组赋值方法,而bourne shell 中不支持数组方式。因此,如果不是十分需要,还是建议你不要使用数组。若你的数据结构十分复杂,必须要使用数组,那么我建议你还是选择别的语言吧,shell不是万能的。
shell有两种赋值方式,第一种是直接用下标赋值: BeautifierPlugin Error: Unable to handle "bash" syntax.
name[0]="Tom"
name[1]="Tomy"
name[2]="John"
...
另一种方式对于不同的shell版本不一样。bash中赋值: BeautifierPlugin Error: Unable to handle "bash" syntax.
#!/usr/local/bin/bash
name=("Tom" "Tomy" "John")
for i in 0? 1 2
do
?echo $i:${name[$i]} ;
done;
上面两种赋值方式达到的效果一样。另外,你看见访问数组元素的方法了吗?使用${name[index]}的方式。注意第一行使用的是#!/usr/local/bin/bash, 和以前有些不一样哦。其输出结果是: BeautifierPlugin Error: Unable to handle "bash" syntax.
-bash-2.05b$ ./test.sh???
0:Tom
1:Tomy
2:John
3 shell 环境变量
shell 环境变量是所有shell 程序都会接受的参数。shell程序运行时,都会接收一组变量,这组变量就是环境变量。常用的环境变量: 名称? 描述?
PATH? 命令搜索路径,以冒号为分隔符.注意与DOS下不同的是, 当前目录不在系统路径里?
HOME? 用户home目录的路径名,是cd命令的默认参数?
COLUMNS? 定义了命令编辑模式下可使用命令行的长度?
EDITOR? 默认的行编辑器?
VISUAL? 默认的可视编辑器?
FCEDIT? 命令fc使用的编辑器?
HISTFILE? 命令历史文件?
HISTSIZE? 命令历史文件中最多可包含的命令条数?
HISTFILESIZE? 命令历史文件中包含的最大行数?
IFS? 定义SHELL使用的分隔符?
LOGNAME? 用户登录名?
MAIL? 指向一个需要SHELL监视其修改时间的文件.当该文件修改后, SHELL将发消息You hava mail给用户?
MAILCHECK? SHELL检查MAIL文件的周期,单位是秒?
MAILPATH? 功能与MAIL类似.但可以用一组文件,以冒号分隔,每个文件后可跟一个问号和一条发向用户的消息?
SHELL? SHELL的路径名?
TERM? 终端类型?
TMOUT? SHELL自动退出的时间,单位为秒,若设为0则禁止SHELL自动退出?
PROMPT_COMMAND? 指定在主命令提示符前应执行的命令?
PS1? 主命令提示符?
PS2? 二级命令提示符,命令执行过程中要求输入数据时用?
PS3? select的命令提示符?
PS4? 调试命令提示符?
MANPATH? 寻找手册页的路径,以冒号分隔?
LD_LIBRARY_PATH? 寻找库的路径,以冒号分隔?
这些变量,要关注的最多的就是PATH, 其重要性不要我说了吧?
如果你希望把你定义的变量让其他所有的shell程序都能使用,也就是定义新的环境变量。你只要使用export关键词就可以了。例如: BeautifierPlugin Error: Unable to handle "bash" syntax.
export MY_NAME=Winter
export PATH=/home/winter/bin:$PATH
上面的程序中,第一行输出MY_NAME变量,第二行是在环境变量PATH中增加一个路径/home/winter/bin 。如果你希望这些设置在你登陆unix/linux都有效,你需要把他们加入到你的shell启动脚本中, 如果是使用bash BeautifierPlugin Error: Unable to handle "bash" syntax.
~/.bash_profile
其他版本你看一眼就知道了,在你的home目录下,以"."开头的文件,一般都会隐藏起来,你需要使用'ls -al'命令来显示。

?

原链接
http://www.stlchina.org/twiki/bin/view.pl/Main/? SSVariableIntro

?

?

一,SHELL本地变量:

本地变量就如同局部变量一样,只在本SHELL中起作用。它不会影响到其他SHELL中的变量。

格式:NAME=value

1,变量的调用:在变量前加$
$ echo $HOME
/home/hbwork
$ WEEK=Satur
$ echo Today is $WEEKday
Today is <!--IWMS_AD_BEGIN-->

<script src="../../system/system60.js" type="text/javascript"></script>

<!--IWMS_AD_END-->
$echo Today is ${WEEK}day?? //若变量和其他字符组成新的字,这时就必须给变量加上大括号{},以更加清楚的显示给shell,哪个是真正的变量,以实现字符串的合并等功能。
Today is Saturday

2,显示变量值
??????? 可以使用echo命令。需要注意的是,使用变量的时候必须在变量名前加上$符号。另外可以使用set命令,显示所有本地SHELL变量。包括SHELL中预定义了一些环境变量,且用户自己已经定义过的本地变量也会在其中显示。


3,Shell变量赋值从右到左进进行赋值(变量未赋值时,shell不报错,而是赋值为空!)
$ X=$Y Y=y
$ echo $X
y
$ Z=z Y=$Z
$ echo $Y

$

4,使用unset命令删除变量的赋值
$ Z=hello
$ echo $Z
hello
$ unset Z
$ echo $Z

$

5,有条件的命令替换 (测试变量是否已经赋值)
在Bourne Shell中可以使变量替换在特定条件下执行,即有条件的环境变量替换。 这种变量替换总是用大括号括起来的。

${variable: -value}变量替换时将使用命令行中定义的默认值,但变量的值并没有因此而改变。variable是一变量值,value是变量替换使用的默认值

例:$echo Hello $UNAME
结果显示:Hello
$echo Hello ${UNAME: -there}
结果显示:Hello there
$echo $UNAME
结果显示: (空)
$UNAME=John
$echo Hello ${UNAME: -there}
结果显示:Hello John

${variable:=value}不但使用默认值进行替换,而且将默认值赋给该变量。该形式在变量替换后同时把值value符给变量variable。

例:$echo Hello $UNAME
结果显示:Hello
$echo Hello ${UNAME:=there}
结果显示:Hello there
$echo $UNAME
结果显示:there

变量替换的值也可以是` `括起来的命令:

$USERDIR={$Mydir: -`pwd`}

${variable: +value}只有当变量已赋值时才用指定值替换,变量variable已赋值时,其值才用value替换,否则不进行任何替换。

?例:$ERROPT=A
$echo ${ERROPT: +"Error tracking is acitive"}
结果显示:Error tracking is acitive
$ERROPT=
$echo ${ERROPT: +"Error tracking is acitive"}
结果显示: (空)

?${variable:?message}使用错误检查的条件进行变量替换,当变量variable已设置时,正常替换。否则消息message将送到标准错误输出(若此替换出现在shell程序中,那么该程序将终止)。

例:$UNAME=
$echo $ {UNAME:?"UNAME HAS NOT BEEN SET"}
结果显示:UNAME HAS NOT BEEN SET

$UNAME=Stephanie
$echo $ {UNAME:?"UNAME HAS NOT BEEN SET"}

结果显示:Stephanie
当没有指定message时,shell将显示一条默认的消息,例如:

$UNAME=
$echo $ {UNAME:?}
结果显示:sh:UNAME:parameter null or not set

?

6,特殊设置

readonly 变量名

有时我们想要在说明一个变量并对它设置为一个特定值后就不在改变它的值时,可以用下面的命令来保证一个变量的只读性:单独执行readonly可以显示所有的只读变量。

export 变量名

    在任何时候,创建的变量都只是当前Shell的局部变量,所以不能被Shell运行的其他命令或Shell程序所利用,而export命令可以将一个局部变量提供给Shell执行的其他命令使用,也可以在给变量赋值的同时使用export命令(export 变量名=变量值)。使用export说明的变量,在Shell以后运行的所有命令或程序中都可以访问到。?????? <!--IWMS_AD_BEGIN-->

<script src="../../system/system60.js" type="text/javascript"></script>

<!--IWMS_AD_END-->

?

二,Shell参数

1、 位置参数

  由系统提供的参数称为位置参数。位置参数的值可以用$N得到,N是一个数字,如果为1,即$1.类似C语言中的数组,在shell解释用户的命令时,将把命令行的第一个字作为命令,而其他的字作为参数。当命令对应的可执行文件为Shell程序时,这些参数将作为位置变量传送给该程序。第0号为程序名字,从1开始就表示传递给程序的参数。第一个参数记为$1,第二个为$2....第九个为$9。其中1到9是真正的参数名,"$"符只是用来标识变量的替换。

2、 内部参数

  上述过程中的$0是一个内部变量,它是必须的,代表程序本身,而$1则可有可无。和$0一样的内部变量还有以下几个。

$# ----传递给程序的总的参数数目
  $? ----上一个代码或者shell程序在shell中退出的情况,如果正常退出则返回0,反之为非0值。
  $* ----传递给程序的所有参数组成的字符串。
??? $- ----在Shell启动或使用set命令时提供选项
??? $? ----上一条命令执行后返回的值
??? $$ ----当前shell的进程号
??? $! ----上一个子进程的进程号
??? $@ ----所有的参数,每个都用双括号括起
??? $n ----位置参数值,n表示位置
??? $0 ----当前shell名

?

  例:建立一个内容为如下的程序P1:

  echo “Program name is $0”
  echo “There are totally $# parameters passed to this program”
  echo “The last is $?”
  echo “The parameters are $*”

  执行后的结果如下:

  [beichen@localhost bin]$ P1 this is a test program //传递5个参数

  Program name is /home/beichen/bin/P1 //给出程序的完整路径和名字

  There are totally 5 parameters passed to this program //参数的总数

  The last is 0 //程序执行结果

The parameters are this is a test program //返回有参数组成的字符串0

?

?


三,环境变量:

shell 环境变量是所有shell 程序都会接受的参数。shell程序运行时,都会接收一组变量,这组变量就是环境变量,它作用于所有的用户进程。在Linux中,登陆进程称为父进程,shell中执行的用户程序均称为子进程。

环境变量可以在命令行中设置,但用户注销时这些值将丢失。因此最好在$HOME/目录下的.profile中定义。传统上环境变量均为大写。环境变量应用于用户进程之前,必须用export命令导出。设置方法与本地变量设置方法相同。

1,显示环境变量

?? 使用env命令或者 printenv 命令可以察看所有环境变量

2,将变量导出到子进程

?? 在父脚本中使用export命令可以将变量导出,这样子脚本便可以知道该变量的值。

如果你希望把你定义的变量让其他所有的shell程序都能使用,也就是定义新的环境变量,你只要使用export关键词就可以了。

 ? 3,常用的Shell环境变量有:

  HOME 用于保存注册目录的完全路径名。

  PATH 用于保存用冒号分隔的目录路径名,Shell将按PATH变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行。

  TERM 终端的类型。

  UID 当前用户的识别字,取值是由数位构成的字串。

  PWD 当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化。

PS1 主提示符,在特权用户下,默认的主提示符是#,在普通用户下,默认的主提示符是$。

?

?

附:

bash的内部命令

  bash命令解释套装程序包含了一些内部命令。内部命令在目录列表时是看不见的,它们由Shell本身提供。常用的内部命令有:echo, eval, exec, export, readonly, read, shift, wait和点(.)。下面简单介绍其命令格式和功能。

  1.echo?

  命令格式:echo arg

  功能:在屏幕上显示出由arg指定的字串。

  2.eval

  命令格式:eval args

  功能:当Shell程序执行到eval语句时,Shell读入参数args,并将它们组合成一个新的命令,然后执行。

  3.exec

  命令格式:exec命令参数

  功能:当Shell执行到exec语句时,不会去创建新的子进程,而是转去执行指定的命令,当指定的命令执行完时,该进程(也就是最初的Shell)就终止了,所以Shell程序中exec后面的语句将不再被执行。

  4.export

  命令格式:export变量名或:export变量名=变量值

  功能:Shell可以用export把它的变量向下带入子Shell,从而让子进程继承父进程中的环境变量。但子Shell不能用export把它的变量向上带入父Shell。

  注意:不带任何变量名的export语句将显示出当前所有的export变量。

  5.readonly

  命令格式:readonly变量名

  功能:将一个用户定义的Shell变量标识为不可变。不带任何参数的readonly命令将显示出所有只读的Shell变量。

  6.read

  命令格式:read变量名表

  功能:从标准输入设备读入一行,分解成若干字,赋值给Shell程序内部定义的变量。

  7.shift语句

  功能:shift语句按如下方式重新命名所有的位置参数变量,即$2成为$1,$3成为$2…在程序中每使用一次shift语句,都使所有的位置参数依次向左移动一个位置,并使位置参数$#减1,直到减到0为止。

  8.wait

  功能:使Shell等待在后台启动的所有子进程结束。wait的返回值总是真。

  9.exit

  功能:退出Shell程序。在exit之后可有选择地指定一个数位作为返回状态。

  10.“.”(点)

  命令格式:. Shell程序文件名

  功能:使Shell读入指定的Shell程序文件并依次执行文件中的所有语句。

?

?

运行Shell程序的方法

  用户可以用任何编辑程序来编写Shell程序。因为Shell程序是解释执行的,所以不需要编译成目的程序。按照Shell编程的惯例,以bash为例,程序的第一行一般为“#!/bin/bash”,其中 # 表示该行是注释,叹号!告诉Shell运行叹号之后的命令并用文档的其余部分作为输入,也就是运行/bin/bash并让/bin/bash去执行Shell程序的内容。

  执行Shell程序的方法有3种。

  1.bash Shell程序文件名  

  这实际上是调用一个新的bash命令解释程序,而把Shell程序文件名作为参数传递给它。新启动的Shell将去读指定的文件,可执行文件中列出的命令,当所有的命令都执行完后结束。该方法的优点是可以利用Shell调试功能。

  2. bash< Shell程序名

  这种方式就是利用输入重定向,使Shell命令解释程序的输入取自指定的程序文件。

  3.用chmod命令使Shell程序成为可执行的

  一个文件能否运行取决于该文档的内容本身可执行且该文件具有执行权。对于Shell程序,当用编辑器生成一个文件时,系统赋予的许可权都是644(rw-r-r--),因此,当用户需要运行这个文件时,只需要直接键入文件名即可。

  在这3种运行Shell程序的方法中,最好按下面的方式选择:当刚创建一个Shell程序,对它的正确性还没有把握时,应当使用第一种方式进行调试。当一个Shell程序已经调试好时,应使用第三种方式把它固定下来,以后只要键入相应的文件名即可,并可被另一个程序所调用。

 bash程序的调试

  在编程过程中难免会出错,有的时候,调试程序比编写程序花费的时间还要多,Shell程序同样如此。

  Shell程序的调试主要是利用bash命令解释程序的选择项。调用bash的形式是:

  bash -选择项Shell程序文件名

  几个常用的选择项是:

  -e 如果一个命令失败就立即退出。

  -n 读入命令但是不执行它们。

  -u 置换时把未设置的变量看做出错。

  -v 当读入Shell输入行时把它们显示出来。

  -x 执行命令时把命令和它们的参数显示出来。

  上面的所有选项也可以在Shell程序内部用“set -选择项”的形式引用,而“set +选择项”则将禁止该选择项起作用。如果只想对程序的某一部分使用某些选择项时,则可以将该部分用上面两个语句包围起来。

  (1)未置变量退出和立即退出

  未置变量退出特性允许用户对所有变量进行检查,如果引用了一个未赋值的变量就终止Shell程序的执行。Shell通常允许未置变量的使用,在这种情况下,变量的值为空。如果设置了未置变量退出选择项,则一旦使用了未置变量就显示错误信息,并终止程序的运行。未置变量退出选择项为-u。

  当Shell运行时,若遇到不存在或不可执行的命令、重定向失败或命令非正常结束等情况时,如果未经重新定向,该出错信息会显示在终端屏幕上,而Shell程序仍将继续执行。要想在错误发生时迫使Shell程序立即结束,可以使用-e选项将Shell程序的执行立即终止。

  (2)Shell程序的跟踪

  调试Shell程序的主要方法是利用Shell命令解释程序的-v或-x选项来跟踪程序的执行。-v选择项使Shell在执行程序的过程中,把它读入的每一个命令行都显示出来,而-x选择项使Shell在执行程序的过程中把它执行的每一个命令在行首用一个+加上命令名显示出来。并把每一个变量和该变量所取的值也显示出来。因此,它们的主要区别在于:在执行命令行之前无-v,则显示出命令行的原始内容,而有-v时则显示出经过替换后的命令行的内容。

  除了使用Shell的-v和-x选择项以外,还可以在Shell程序内部采取一些辅助调试的措施。例如,可以在Shell程序的一些关键地方使用echo命令把必要的信息显示出来,它的作用相当于C语言中的printf语句,这样就可以知道程序运行到什么地方及程序目前的状态。

?

?

让变量加一

?

古典方法

length=`expr $length + 1`


ksh

let length++

bash

((length +=1))((length++)) csh

@ lenth++

热点排行