Chinaunix首页 | 论坛 | 博客
  • 博客访问: 643954
  • 博文数量: 227
  • 博客积分: 8017
  • 博客等级: 中将
  • 技术积分: 2069
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-08 22:50
文章分类

全部博文(227)

文章存档

2011年(10)

2010年(55)

2009年(28)

2008年(134)

我的朋友

分类: LINUX

2008-05-11 16:32:00

一直都想学习好脚本,可是总是没有认认真真地学过。 这几天看ULK实在是看不下去了(看得有点多!),正好学学Bash吧!

第一部分 基本
1. 特殊字符
  • #  注释
  • ;  命令分隔符,可以在同一行上写两个或两个以上的命令
  • `  命令替换. `command` 结构可以将命令的输出赋值到一个变量中去.
  • :  空命令, 等价于"NOP", Bash内建命令。
  • $? 退出状态码变量,保存了一个命令, 一个函数或者是脚本本身的退出状态码。
  • $$ 进程ID变量. 这个 保存了它所在脚本的进程 ID
  • ~+ 当前工作目录. 相当于内部变量.
  • ~- 先前的工作目录. 相当于内部变量.
2. 变量和参数
  • 变量引用的方式
    • $(var) 或$var, 其中$var 只是$(var)的简写形式。在某些上下文中$var可能会引起错误, 这时候你就需要用${var}
    • var=test; echo "$var" #输出 test 等同于echo $var, ""是弱引用
    • echo '$var' #输出 $var, ''是强引用, 其中的所有特殊字符不会被解释
  • 变量赋值
    • =  赋值操作(前后都不能有空白)
    • var="hello,world";echo $var  #hello,world
    • res=`ls -l`;echo $res ## `ls -l` 返回ls -l命令的结果,它等同于 $(ls -l),只不过后者是一种比较新的写法.
  • Bash变量是不区分类型的
    • 不像其他程序语言一样, Bash并不对变量区分"类型". 本质上, Bash变量都是字符串. 但是依赖于具体的上下文, Bash也允许比较操作和整数操作. 其中的关键因素就是, 变量中的值是否只有数字.
  • 特殊的变量类型
    • 局部变量:这种变量只有在代码块或者函数中
    • 环境变量:这种变量将影响用户接口和shell的行为, 每次当一个shell启动时, 它都将创建适合于自己环境变量的shell变量. 更新或者添加一个新的环境变量的话,后继生成的子进程会继承Shell的新环境变量, 已经运行的子进程并不会得到它的新环境变量。 可用export向当前shell或脚本的子进程输出变量!
    • 位置参数:
      • 从命令行传递到脚本的参数: $0, $1, $2, $3 .. ${10},${11}... 其中$0就是脚本文件自身的名字, $1 是第一个参数, $2是第二个参数
      • $* , $@代表所有的命令行参数(位置参数)
      • $# , 参数个数
      • shift命令会重新分配位置参数, 其实就是把所有的位置参数都向左移动一个位置
    • 打印命令行参数:
    • #!/bin/bash
      echo "The name of this scripts $(basename $0)"
      echo "there are $# args"
      echo "if get the params..."
      if [ -n "$1" ];then
          echo '$1=' $1
      fi

      if [ -n "$2" ];then
          echo '$2=' $2
      fi

      echo "for circle get params..."
      for arg in $@; do
          echo -n "$arg "
      done
      echo

      echo "shift & until get params... "
      until [ -z "$1" ];do
          echo -n "$1  "
          shift
      done
      exit 0
  • 退出状态和退出码:
    • exit 被用来结束一个脚本, 就像在C语言中一样. 它也返回一个值, 并且这个值会传递给脚本的父进程, 父进程会使用这个值做下一步的处理. 每个命令都会返回一个退出状态码(有时候也被称为 返回状态). 成功的命令返回0, 而不成功的命令返回非零值, 非零值通常都被解释成一个错误码.
    • 当脚本以不带参数的exit命令来结束时, 脚本的退出状态码就由脚本中最后执行的命令来决定
    • $?保存了最后所执行的命令的退出状态码. 当函数返回之后, $?保存函数中最后所执行的命令的退出状态码. 这就是bash对函数"返回值"的处理方法. 当一个脚本退出, $?保存了脚本的退出状态码, 这个退出状态码也就是脚本中最后一个执行命令的退出状态码. 一般情况下, 0表示成功, 在范围1 - 255的整数表示错误.
3. 条件判断
  • 条件测试结构:
    • if/then结构用来判断命令列表的退出状态码是否为0(因为在UNIX惯例, 0表示"成功"), 如果成功的话, 那么就执行接下来的一个或多个命令. (if/then/elif/then/fi)
    • 有一个专有命令[ ,这个命令与test命令等价, 并且出于效率上的考虑, 这是一个内建命令. 这个命令把它的参数作为比较表达式或者作为文件测试, 并且根据比较的结果来返回一个退出状态码(0 表示真, 1表示假).
    • 在版本2.02的Bash中, 引入了[[...]]扩展测试命令, Bash把[[ $a -lt $b ]]看作一个单独的元素, 并且返回一个退出状态码.
    • ((...))和let ... 结构也能够返回退出状态码, 当它们所测试的算术表达式的结果为非零的时候, 将会返回退出状态码0. 这些算术扩展结构被用来做算术比较.
    • let "1<2"; echo $?  #0
    • ((0 && 1)); echo $? #1
    • 实例:
      #!/bin/bash
      ##learning if/else
      if cmp a b &> /dev/null #禁止输出
      then echo "a b are identical"
      else echo "a,b are different"
      fi

      word=Linux
      fseq=inu
      if echo "$word"|grep -q "$fseq"  ##-q用来禁止输出
      then echo "$fseq was found in $word"
      else echo "$fseq was not found in $word"
      fi

      exit 0
               
    • Else if和elif
      • if [ condition1 ]
        then command1;command2
        elif [ condition2 ] # 与else if一样
        then command4;command5
        else
        default-command
        fi
    • test, /usr/bin/test, [ ], 和/usr/bin/[都是等价命令 (可用type test,type '['验证)
      • 例如: if test -z "$1" 等价于 if [ -z "$1" ]
      • [[ ]]结构比[ ]结构更加通用. 这是一个扩展的test命令, [[]]之间所有的字符都不会发生文件名扩展或者单词分割, 但是会发生参数扩展和命令替换. 使用[[ ... ]]条件判断结构, 而不是[ ... ], 能够防止脚本中的许多逻辑错误. 比如, &&, ||, <, 和> 操作符能够正常存在于[[ ]]条件判断结构中, 但是如果出现在[ ]结构中的话, 会报错.
      • example:
        file=/etc/passwd
        if [[ -e $file ]]
        then echo "$file exist!"
        else echo "$file not exist!"
        fi
    • ((...)) 扩展并计算一个算术表达式的值. 如果表达式的结果为0, 那么返回的退出状态码为1, 或者是"假". 而一个非零值的表达式所返回的退出状态码将为0, 或者是"true". 这种情况和先前所讨论的test命令和[ ]结构的行为正好相反. example
      • ((0));echo $? #1
      • ((5 > 4));echo $? #0
      • ((1/0)) 2>/dev/null;echo $? #1
  • 文件测试操作
    • 如果下面的条件成立将会返回真
      • -e :True if file exists
      • -f :True if file exists and is a regular file.(equal -a)
      • -s :True if file exists and has a size greater than zero
      • -d :True if file exists and is a directory.
      • -b :True if file exists and is a block special file
      • -c :True if file exists and is a character special file.
      • -p :True if file exists and is a named pipe (FIFO).
      • -h :True if file exists and is a symbolic link. (equal -L)
      • -S :True if file exists and is a socket.
      • -t :True if file descriptor fd is open and refers to a terminal.
      • -r :True if file exists and is readable.
      • -w :True if file exists and is writable.
      • -g :True if file exists and is set-group-id.
      • -u :True if file exists and its set-user-id bit is set.
      • -k :True if file exists and its ‘‘sticky’’ bit is set.
      • -O :True if file exists and is owned by the effective user id.
      • -G :True if file exists and is owned by the effective group id.
      • -N :True if file exists and has been modified since it was last read.
      • file1 -nt file2 : True  if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
      • file1 -ot file2 : True if file1 is older than file2, or if file2 exists and file1 does  not.
      • file1 -ef file2 :True if file1 and file2 refer to the same device and inode numbers.(they are hardlinks?)
      • ! :"非" -- 反转上边所有测试的结果(如果没给出条件, 那么返回真).
  • 其他比较操作符
    • 整数比较:
      • -eq :equal,  example: if [ "$a" -eq "$b" ]
      • -ne :none equal
      • -gt :greater than
      • -ge :greater equal
      • -lt :less than
      • -le :less equal
      • <, <=, >, >= 这几个比较符只能在[[...]]中使用, example: (("$a" >= "$b"))
    • 字符串比较
      • -z string: True if the length of string is zero
      • -n string: True if the length of string is non-zero.
      • string1 == string2 :True if the strings are equal.  (=等同于==)
      • string1 != string2 :True if the strings are not equal.
      • string1 < string2  :True  if  string1  sorts  before  string2 lexicographically in the current locale.(字典顺序, 注意"<"使用在[ ]结构中的时候需要被转义. exmaple: if [[ "$a" < "$b" ]] <==> if [ "$a" \< "$b" ])
      • string1 > string2  :True if string1 sorts  after  string2  lexicographically  in  the  current locale.
      • ==比较操作符在[[...]]和单中括号对中的行为是不同的.例如: 
        • [[ $a == z* ]]   # 如果$a以"z"开头(模式匹配)那么结果将为真 
        • [[ $a == "z*" ]] # 如果$a与z*相等(就是字面意思完全一样), 那么结果为真.
        • [ $a == z* ]     # 文件扩展匹配(file globbing)和单词分割有效.
        • [ "$a" == "z*" ] # 如果$a与z*相等(就是字面意思完全一样), 那么结果为真.
      • -a :逻辑与, exp1 -a exp2 如果表达式exp1和exp2为真的话, 那么结果为真.
      • -o :逻辑或, exp1 -o exp2 如果表达式exp1和exp2中至少有一个为真的话, 那么结果为真. (-o-a操作符一般都是和test命令或者是单中括号结构一起使用的. example: if [ "$exp1" -a "$exp2" ])
4. 操作符与相关主题:
  • 操作符 
    •        id++ id--
                    variable post-increment and post-decrement
             ++id --id
                    variable pre-increment and pre-decrement
             - +    unary minus and plus
             ! ~    logical and bitwise negation
             **     exponentiation
             * / %  multiplication, division, remainder
             + -    addition, subtraction
             << >>  left and right bitwise shifts
             <= >= < >
                    comparison
             == !=  equality and inequality
             &      bitwise AND
             ^      bitwise exclusive OR
             |      bitwise OR
             &&     logical AND
             ||     logical OR
             expr?expr:expr
                    conditional operator
             = *= /= %= += -= <<= >>= &= ^= |=
                    assignment
             expr1 , expr2
                    comma
    • example: let "var += 9"; let "var**2"; let "n++"; ((n++))#C风格的增量操作
    • Bash不能够处理浮点运算. 它会把包含小数点的数字看作字符串. 故 t=1.5;((t++))会出错。
    • if [ condition1 ] && [ condition2 ] <==> if [condition1 -a condtion2] <==> if [[ condition1 && condition2 ]] #注意: &&不允许出现在[ ... ]结构中.
    • if [ condition1 ] || [ condition2 ] <==> if [condition1 -o condtion2] <==> if [[ condition1 || condition2 ]] #注意: ||不允许出现在[ ... ]结构中.
  • 数字常量
    • shell脚本在默认情况下都是把数字作为10进制数来处理, 除非这个数字采用了特殊的标记或者前缀. 如果数字以0开头的话那么就是8进制数. 如果数字以0x开头的话那么就是16进制数. 如果数字中间嵌入了#的话, 那么就被认为是BASE#NUMBER形式的标记法(有范围和符号限制).
阅读(664) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~