shell编程入门篇

 一,建立脚本
           Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行shell编程,因为bash是免费的并且很容易使用。
        所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下,这些脚本同样可以在bash的大姐,bourne shell中运行)。

  如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写我们的shell程序。

       #!/bin/sh
       符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
        当编辑好脚本时,如果要执行该脚本,还必须使其可执行。
  要使脚本可执行:
  chmod +x filename
  然后,您可以通过输入: ./filename 来执行您的脚本。


二,注释
  在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。


三,变量
  1.系统变量
     $n  n代表具体的位置,$1表示第一个参数,$2表示第二个参数 ... 
     $#  命令行参数的个数 
     $0  当前程序的名称 
     $?  前一个命令或函数的返回码 
     $*  以"参数1 参数2 ... " 形式保存所有参数 
     $@  以"参数1" "参数2" ... 形式保存所有参数 
     $$  本程序的(进程ID号)PID 
     $!  上一个命令的PID
     $-  在Shell启动或使用set命令时提供选项


  2.环境变量
     shell 环境变量是所有shell 程序都会接受的参数。shell程序运行时,都会接收一组变量,这组变量就是环境变量。
    1)常用环境变量
      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  寻找库的路径,以冒号分隔
   
  3.用户变量或本地变量
     本地变量就如同局部变量一样,只在本SHELL中起作用。它不会影响到其他SHELL中的变量。
   1)变量命名
      用户定义的变量必须由字母数字及下划线组成,并且变量名的第一个字符不能为数字, 与其它UNIX名字一样,变量名是大小写敏感的.


   2)变量赋值
      Shell变量赋值从右到左进进行赋值(变量未赋值时,shell不报错,而是赋值为空!) 
      name="Winter"
      注意:变量和'='之间不要有空格,'='和赋值也不要有空格,否则shell不会认为变量被定义
    
      特殊举例:
      X=$Y Y=y
      echo $X
      输出:y
    
       Z=z Y=$Z
      echo $Y
      输出:

    
   3)变量调用:在变量前加$
      WINTER=$name
    
      注意:变量调用时使用花括号{}来区别变量名和其它字符
      num=2
    echo "this is the $numnd"
      打印输出:this is the
   
       num=2
  echo "this is the ${num}nd"
   打印输出:this is the 2nd

   
   4)显示变量值
    echo "Hello $WINTER !"
     set 显示所有本地SHELL变量。包括SHELL中预定义了一些环境变量,且用户自己已经定义过的本地变量也会在其中显示
    
   5)unset命令删除变量的赋值
    Z=hello
    unset Z
       
    6)特殊设置
    readonly 变量名
    有时我们想要在说明一个变量并对它设置为一个特定值后就不在改变它的值时,可以用下面的命令来保证一个变量的只读性:单独执行readonly可以显示所有的只读变量。
    
    export 变量名
    在任何时候,创建的变量都只是当前Shell的局部变量,所以不能被Shell运行的其他命令或Shell程序所利用,而export命令 可以将一个局部变量提供给Shell执行的其他命令使用,也可以在给变量赋值的同时使用export命令(export 变量名=变量值)。使用export说明的变量,在Shell以后运行的所有命令或程序中都可以访问到
    
    export MY_NAME=Winter
    export PATH=/home/winter/bin:$PATH
    第一行输出MY_NAME变量,第二行是在环境变量PATH中增加一个路径/home/winter/bin
    
    如果你希望这些设置在你登陆unix/linux都有效,你需要把他们加入到你的shell启动脚本中, 如果是使用bash
    ~/.bash_profile其他版本你看一眼就知道了,在你的home目录下,以"."开头的文件,一般都会隐藏起来,你需要使用'ls -al'命令来显示

四,shell命令
  1.Unix 命令
   shell脚本中可以使用任意的unix命令,常用命令语法及功能如下

   echo "some text": 将文字内容打印在屏幕上
   ls: 文件列表
   wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数
   cp sourcefile destfile: 文件拷贝
   mv oldname newname : 重命名文件或移动文件
   rm file: 删除文件
   grep 'pattern' file: 在文件内搜索字符串比如:grep 'searchstring' file.txt
   cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,这是两个完全不同的命令
   cat file.txt: 输出文件内容到标准输出设备(屏幕)上
   file somefile: 得到文件类型
   read var: 提示用户输入,并将输入赋值给变量
   sort file.txt: 对file.txt文件中的行进行排序
   uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq
   expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3
   find: 搜索文件比如:根据文件名搜索find . -name filename -print
   tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile
   basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tux
   dirname file: 返回文件所在路径比如:dirname /bin/tux将返回 /bin
   head file: 打印文本文件开头几行
   tail file : 打印文本文件末尾几行
   sed: Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus 替换为 LinuxFocus :cat text.file | sed 's/linuxfocus/LinuxFocus/' > newtext.file
   awk: awk 用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。cat file.txt | awk -F, '{print $1 "," $3 }'这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如下: Adam Bor, 34, IndiaKerry Miller, 22, USA命令输出结果为:Adam Bor, IndiaKerry Miller, USA

  2.管道, 重定向和 反短斜线(backtick)
         管道 (|) 将一个命令的输出作为另外一个命令的输入。
   grep "hello" file.txt | wc -l
   在file.txt中搜索包含有”hello”的行并计算其行数。在这里grep命令的输出作为wc命令的输入。

        重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。
   > 写入文件并覆盖旧文件
   >> 加到文件的尾部,保留旧文件内容。

         反短斜线
   使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。

         命令:
   find . -mtime -1 -type f -print
   用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:
   #!/bin/sh
   # The ticks are backticks (`) not normal quotes ('):
   tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`

   3.shift
      shift其实很简单的,就是左移参数列表,shift一次就将最左边的参数$1移出去了,然后 原来的$2现在就变成了$1。

      shift后面还可以带上一个数字,指明要移出多少个参数(默认只移出一个),比如说shift 3 就是移出3个参数,之后原来的$4就变成了现在的$1。
   
  4.eval
     eval就是先将后面的参数执行一遍,将必要的置换都做了,再来执行命令。举个例子:
     MYFILE="cat myfile"
     echo $MYFILE   # output: cat myfile
     eval $MYFILE   # output: contents of myfile
   
    再举个详细点儿的例子:
    #!/bin/bash
    # evalit
    echo " Total number of arguments passed: $#"
    echo " The process ID: $$"
    echo " Last argument: " $(eval echo \$$#)
    运行脚本:
    $ ./evalit alpha bravo charlie
    output as follows:
    Total number of arguments passed: 3
    The process ID: 780
    Last argument:   charlie

 


五,流程控制
  1.if表达式
        if ....; then
     ....
    elif ....; then
    ....
   else
    ....
   fi
      大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存在及是否可读等等…
  通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。
  [ -f "somefile" ] :判断是否是一个文件
  [ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
  [ -n "$var" ] :判断$var变量是否有值
  [ "$a" = "$b" ] :判断$a和$b是否相等

  2.case表达式
       case表达式可以用来匹配一个给定的字符串,而不是数字
      case ... in
        ...) do something here ;;
       esac
  
     file命令可以辨别出一个给定文件的文件类型,比如:
     file lf.gz 这将返回:
     lf.gz: gzip compressed data, deflated, original filename,last modified: Mon Aug 27 23:09:18 2001, os: Unix
    我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2, gzip 和zip 类型的压缩文件:
    #!/bin/sh
    ftype=`file "$1"`
     case "$ftype" in
    "$1: Zip archive"*)
     unzip "$1" ;;
    "$1: gzip compressed"*)
    gunzip "$1" ;;
    "$1: bzip2 compressed"*)
    bunzip2 "$1" ;;
    *) error "File $1 can not be uncompressed with smartzip";;
    esac
  
  3.select表达式
   select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户可以从一组不同的值中进行选择。
   select var in ... ; do
    break
   done
   .... now $var can be used ....
   
   下面是一个例子:
   #!/bin/sh
   echo "What is your favourite OS?"
   select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
    break
   done
   echo "You have selected $var"
   下面是该脚本运行的结果:
   What is your favourite OS?
    1) Linux
    2) Gnu Hurd
    3) Free BSD
    4) Other
    #? 1
   You have selected Linux
   
   4.while-loop表达式
    while-loop 如果表达式为真,则继续运行。will run while the expression that we test for is true.
    关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。
    while ...; do
    ....
   done

  5.for-loop表达式
   for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
   for var in ....; do
    ....
   done

   在下面的例子中,将分别打印ABC到屏幕上:
   #!/bin/sh
   for var in A B C ; do
    echo "var is $var"
   done
   
  6.util-loop表达式
   util-loop 与while-loop表达式正好相反,直到表达式为真,循环退出。
   util ...; do
    ....
   done
   
   
六,函数
  如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相同的代码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:
  functionname()
  {
   # inside the body $1 is the first argument given to the function
   # $2 the second ...
   body
  }
  
  您需要在每个程序的开始对函数进行声明。
  #!/bin/sh
  # vim: set sw=4 ts=4 et:

  help()
  {
   cat <<HELP
   xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole

   USAGE: xtitlebar [-h] "string_for_titelbar"

   OPTIONS: -h help text

   EXAMPLE: xtitlebar "cvs"

   HELP
   exit 0
  }

  # in case of error or if -h is given we call the function help:
  [ -z "$1" ] && help
  [ "$1" = "-h" ] && help

  # send the escape sequence to change the xterm titelbar:
  echo -e "33]0;$107"
  #
  在脚本中提供帮助是一种很好的编程习惯,这样方便其他用户(和您)使用和理解脚本。
  当要将几行文字传递给一个命令时,here documents(译者注:目前还没有见到过对该词适合的翻译)一种不错的方法。
  对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个here documents就不必用echo函数一行行输出。
  一个 "Here document" 以 << 开头,后面接上一个字符串,这个字符串还必须出现在here document的末尾。

七,其它
  1.引号防止通配符扩展
    #!/bin/sh
    echo "*.jpg"
    echo '*.jpg'
   
    备注:单引号更严格一些。它可以防止任何变量扩展。双引号可以防止通配符扩展但允许变量扩展。
    #!/bin/sh
    echo $SHELL
    echo "$SHELL"
    echo '$SHELL'

    运行结果为:
    /bin/bash
    /bin/bash
    $SHELL

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值