首页 > 技术文章 > linux shell编程

heml 2015-04-30 01:46 原文

 

 

         shell是一种命令语言,同时又是一种程序设计语言。shell的语言处理能力,使得用户能够方便地定义各种变量、参数,并使用各种控制语句编写复杂的命令程序完成多种工作。

 

         shell是一种命令解释程序(命令解释器)shell解释用户输入的命令行,提交系统内核处理,并将结果返回给用户。与Linux命令一样都是实用程序,但两者又有区别。一旦用户注册到系统后,shell就被系统装入内存,并一直运行到用户退出系统之止;而一般命令仅当被调用时,才由系统装入内存执行。

       

        shell本身也是一种可编程的程序设计语言。用shell写的程序(shell脚本)相当于dos/windows下的批处理文件,它可以简单到只有一条命令,也可以复杂到包括大量循环、条件语句、数学运算、控制结构,也可以是介于两者之间的程序。

 

 

  shell程序语言的特点,shell允许通过编程来完成复杂的功能处理,但其作为语言与高级语言相比较具有不同的特点:

         *  shell是解释性的,多数高级语言是编译性的;

         *  shell语言与高级语言处理的对象不同;

         *  shell与系统有密切的关系;

         *  shell易编写、调试、灵活性较强,但速度低;

         *  shell作为命令级语言,命令组合功能很强。

 

shell的版本

        shell有两种主要语法类型: Bourne shellC shell,彼此不兼容。

                 * Bourne shell家族:sh ksh bash psh zsh

                 * C shell家族:csh tcsh

其中bashzsh在不同程度上支持 csh 的语法。

 

bash的特点:

(1) 自动补全功能

    假设要输入的命令很长,或者命令后面要给的文件名很长。这个时候只要按一个Tabbash就会在可能的命令或文件名里面找寻匹配的命令,找到的话就会自动帮你补齐

(2) 命令行编辑程序

bash的命令行编辑是在提示符下,可对未执行的命令字符任意地修改。

(3) 命令历史(command history)

    所谓的命令历史就是把曾经输入过的命令记录起来,方便日后的查询与使用。只要按向上键就可以调出前一个命令,再按一次向上键就可以调出更前一个命令,依此类推,用向下键可以回到下个命令,所以用上、下键就可以选择以前输入过的命令。

linux中常用的元字符:

..    上一层目录,与cd命令配合用得比较多

.     目前工作的目录

*    任意长度的字符

?  长度为一个的任意字符

[..]   括号内的一个字符

\m      等于某个通配符,如*、?等

[a-z]*   小写字母开头的所有字符串

\        转义符号,用以解除特殊字符的特殊意义

~          用户目录

;        分隔符,当命令行有多个命令时,做分隔用

$        BourneShell的提示符,同时也作为shell语言的位置变量参数

#          做注释用

|           建立一个管道,使一命令的输出作为另一个命令的输入

&        将命令以后台方式执行

>       将命令的输出重导入文件中

<       将命令的输入流指定为由文件中加载,和>相反

>>     将命令的输出加在一个已经存在的文件后面

{..}     括号内的一个字符串

 

在系统中可能有多种版本的shell存在,可通过相应的命令来启动,如:

$bsh

$ksh

$sh

Linux有丰富的shell命令,大致划分为以下几类:

  • 目录操作与管理
  • 文件操作与管理命令
  • 系统管理与维护
  • 用户管理与维护
  • 系统状态
  • 进程管理
  • 通讯命令
  • 其他命令

shell的内部命令

      内部命令构造在shell的内部。内部命令比非内部命令的执行速度要快。因此,编写shell程序时应尽量地使用shell的内部命令。shell常用的内部命令有:

#            注释命令,#后面的内容作为注释信息。

:             空命令,通常放在一行的最左边,实际不做任何命令,只返回出口代码0。

其他命令有:cd,eval,set,unset,exec,exit,if,else,for,case,while,until,continue,break等

管道和命令表:

管道的概念:

管道:是一个命令的标准输出与另一个命令的标准输入之间的连接,不经过任何中间文件;

管道线:是由管道操作符分隔的一个命令序列,最简单的管道线是一个简单命令;

管道操作符:用符号“|”表示。

命令表的概念:

命令表:一串管道线构成了一个命令表,最简单的命令表是一个管道线,一个命令表送回的值是该命令表中最后一个管道线的出口状态。

管道线分隔符:分隔命令表元素,确定管道线执行的条件。各分隔符含义如下:

;             表示按顺序执行管道线;

&&       表示根据条件(true),执行其后面的管道线;

&           表示前面的管道线在后台(异步)执行。

‖          表示根据条件(false),执行其后面的管道线;  

命令组合:

命令组合有两种形式:  {命令表}(命令表) ,前者只在本shell中执行,不产生新的子进程;后者要产生新的子进程来执行命令表。

例1: { cd  mydoc; rm junk;}

该命令表只能在当前shell下执行,先进入目录mydoc,然后执行rm命令,执行完毕后,当前目录已改变为mydoc

例2: (cd  mydoc; rm junk;)

      当前shell要生成一个子shell进程,由该子shell来执行命令表。子shell完成操作后,自然消亡,而其父shell进程的当前路径并没有变化。

命令替换

    当一个字符串被括在反撇号“ ` ”中时,该字符串将作为命令被shell解释执行,即用命令的执行结果替换这个字符串本身。要注意反撇号与单引号的区别。

       在Linux系统中,定义了用于输入、输出的标准文件,其文件描述字0为进程的标准输入、文件描述字1为标准输出、文件描述字2为标准错误输出如: command  2 >>file

 

 

 

shell变量:

     shell变量描述

shell实际上是基于字符串的程序设计语言,但也有变量。shell变量能够而且只能存储正文字符串,即它只有一种类型的变量即串变量。但从赋值的形式上看,则可以分成四种类型的变量或变量形式。变量的名字必须以字母或下划线开头,可以包括字母、数字和下划线。

用户自定义变量

用户自定义变量语法格式name=string,赋值号“=”两边不允许有空白符

  • * 当引用一个未设置的变量时,其隐含值为空 

    * 如果用双引号“”将值括起来,则括起来的字符串允许出现空格、制表符和换行符等特殊字符,而且允许有变量替换。

 * 如果用单引号‘’将值括起来,则括起来的字符串允许出现空格、制表符和换行符的特殊字符,但不允许有变量替换。

 * 引用变量的值时,可以用花括号{}将变量名称括起来,使变量名称与它的后续字符分隔开,如果紧跟在变量名称后面的字符是字母、数字或下划线时,必须要使用花括号

 

可将变量设置为只读形式,格式为,readonly  变量名1  变量名2

  $ ux=UNIX.SUN

  $ readonly ux

  $ ux=UNIX.SCO

  ux: is read only

查看只读形式的变量,格式为readonly

  $ readonly

  readonly ux

位置变量

        位置变量顾名思义是与变量所在位置有关的变量,这是一种特殊的变量。当一个shell过程被调用时,shell隐含地为它建立一系列的位置变量。这种位置变量是系统预定义好的,可以直接引用。如命令行的shell过程名本身被指定为位置变量$0,第一个命令参数为$1……,第九个命令参数为$9

 

内部命令shift 的作用

       当位置变量个数超出9时,就不能直接引用位置大于9的位置变量了,必须用shift命令存取。每执行一次shift命令,删除$1位置变量,并使其他的所有位置变量向左移动一个位置

用set命令进行强制性赋值,位置变量可以使用set命令进行强制性赋值。

例:

           set   Sun   Mon   Tue   Wed   Thu   Fri   Sat

  结果$1   $2    $3     $4    $5    $6   $7

注意:  $0是不能用这种方法赋值的

预定义的特殊变量:

  • “$#” 记录传递给shell的自变量个数。
  • ?”取最近一次命令执行后的退出状态:执行成功返回码为0,执行失败返回码为1
  • $$”记录当前shell的进程号。

变量替换:

变量替换提供了三种功能:允许替换未设置变量的隐含值允许对未设置变量赋值在访问未设置变量时,提示出错信息

    格式为:${var:-word}:当var没设置时为word  --> 允许替换未设置变量的隐含值

                ${var:-"word"} --> 在访问未设置变量时,提示出错信息

                 ${var:=word" --> 允许对未设置变量赋值

测试变量是否设置格式{TERM:? ″ the TERM varible should be set ″ }

 

特殊字符的引用:

消除特殊字符的含义有3种常用的方法,分别是转义符、单引号和双引号

转义符(\):转义符后面的单个字符按字符本身的实际含义解释

单引号('):使用单引号消除被括在单引号中的所有特殊字符的含义,即单引号表示内容照原样不动

 

     双引号("):使用双引号能消除被括在双引号中的大部分特殊字符的含义,不能消除的字符有:$、 ` 、 \。

test命令:

格式:test expression或[expression

 

 

 

shell在处理变量时,遇到有双引号将保留其内容,而省略双引号时,将滤去空格

 

 

 

 

使用test测试字符串时要注意的问题

(1) test 传递的各自变量之间必须有空白字符,如果“=”与任一自变量之间没有空白字符就会产生错误。

(2) 在使用变量的值替换的自变量上,用双引号括起来十分必要,以保证test在变量的值为空时也能接收到该自变量,这是一种良好的shell程序设计风格。

(3) test命令的测试中,空格和引号是shell程序设计中经常发生错误的焦点,要特别引起注意。

(4) test命令对它的自变量非常讲究,在比较的串中出现运算符时,要考虑到运算符优先级的问题。

 

test用于文件的测试

例1: 检查指定的文件是否存在并且可读

  test  -f  /usr/fk/message

例2: 检查指定的文件是否为目录

  test  -d  /usr/src/local/sendmail

例3: 检查指定的出错文件是否为空,如不空则列出该文件的内容

  test -s $errfile && {echo ″Errors found:″;\

  cat $errfile}

逻辑运算

  • ! :     逻辑非单目运算符,可放置在任何其他test表达式之前,求得表达式运算结果的非值。
  • -a :   逻辑与运算符,执行两个表达式的逻辑与运算,并且仅当两者都为真时,才返回真值。
  • -o :   逻辑或运算符,执行两个表达式的逻辑或运算,并只要当两者之一为真时,就返回真值。

if结构

1. if的简单结构

格式为,

  if command

  then

  command

  command

  ...

  fi

2、if的完整结构

格式为,

  if command

  then

  command

  command

  ...

  else

  command

  command

  ...

  fi

 

  if command

  then

  commands

  elif command

  then

  commands

  elif

  …

  elif commands

  then

  commands

  else

  commands

  fi

 

case结构

格式为,

  case value in

  pattern1)  command

  ...

  command;;

  pattern2)  command

  ...

  command;;

  ...

  patternn)  command

  ...

  command;;

  esac

 

for结构

格式为,

  for  variable in arg1 arg2 ... argn

  do

  command

  ...

  command

  done

while结构

格式为,

  while command

  do

  command

  ...

  command

  done

until结构

  格式为,

  until command

  do

  command

  ...

  command

  done

 

 

循环体中其他命令

1. break命令

格式为,

  break或break n

     break是shell的内部命令,用于在循环体中根据命令运行的返回条件,直接终止循环体内命令的执行。当执行break命令时,控制流从循环体中转移到done之后的第一条命令上。当执行break n命令时,则终止最内层的n个循环的执行。

2. continue 命令

格式为,

  continue或continue  n

continueshell的内部命令,用于在循环体中根据命令运行的返回条件,直接进入下一次循环命令的执行。当执行continue命令时,控制流直接转到本循环体中第一条命令上。当执行continue n命令时,则跳过最里层的 n次循环体的执行,即开始第n(从内向外数) 循环的下一个循环过程。

for  i  in  a  b  c  d

  do

  echo $i

  done|wc -l

函数的定义:

格式为,

  Function Name(){

  command

  …

  command

  }

全局变量 :export  variables

 

 

 

推荐阅读