SHELL脚本-第二课

回顾

  1. shell脚本编程的不适用场景的列举;1
  2. 简单的shell脚本展示;
  3. 解释器说明及注意事项;
  4. 脚本的运行方式。

基础知识

在此,我们将对一些特殊字符,变量命名及常见使用方式做一些介绍,以便你做基本的了解。首先,我们来看看看有哪些特殊的字符值得注意。

特殊字符

脚本中常常会出现一些特殊的字符,他们都表示一些特定的含义,我们接下来对它们做一一的介绍。

  1. #:以一个#开头的行 (#!是例外) 是注释行。例如:

    #这是一行注释.
    
  2. ;:【命令分割符】用分割符允许在同一行里有两个或更多的命令。例如:

    echo hello; echo there
    if [ -x "$filename" ]; then    # 注意:"if" and "then"需要分隔符
                                   # 思考一下这是为什么?
      echo "File $filename exists."; cp $filename $filename.bak
    else
      echo "File $filename not found."; touch $filename
    fi; echo "File test complete."
    
  3. ;;:case语句分支的结束符[双分号]。例如:

    case "$variable" in
    abc)  echo "\$variable = abc" ;;
    xyz)  echo "\$variable = xyz" ;;
    esac
    
  4. ':'STRING’能引用STRING里的所有字符(包括特殊字符也会被原样引用)。这是一个比使用双引号(“)更强的引用。 例如:

    #! /bin/bash
    hello="A B C D"
    echo $hello
    echo "$hello"
    echo '$hello'
    

    运行结果如下所示:

    $bash string
    A B C D
    A B C D
    $hello

    从运行结果可以看出,在单引号中的变量引用会被禁止,字符$会仅仅被认为是一个普通的字符,而不是变量的前缀。

  5. ":"STRING"的引用会使STRING里的特殊字符能够被解释。其中例子如上所示。

  6. .:等同于source。这是一个bash的内建命令。
    在这边.符号可以在脚本中的作用类似于C语言中的#include,可以直接调用#include中的变量以及函数。调用./bbb脚本如下:

    # This is a data file loaded by a script.
    # Files of this type may contain variables, functions, etc.
    # It may be loaded with a 'source' or '.' command by a shell script.
     
    # Let's initialize some variables.
     
    variable1=22
    variable2=474
    variable3=5
    variable4=97
    
    message1="Hello, how are you?"
    message2="Enough for now. Goodbye."
     
    print_message ()
    {
    	#Echoes any message passed to it.	 
    	if [ -z "$1" ]
    	then
    	    return 1
    	    # Error, if argument missing.
    	fi
    	
    	echo	 
    	until [ -z "$1" ]
    	do
    	   # Step through arguments passed to function.
    	   echo -n "$1"
    	   # Echo args one at a time, suppressing line feeds.
    	   echo -n " "
    	   # Insert spaces between words.
    	   shift
    	   # Next one.
    	done  
    	 
    	echo	 
    	return 0
    }  
    

    接下来,通过另外一个脚本调用其中的变量以及函数。例如:

    #!/bin/bash
    . bbb    # Load a data file.
    echo "variable1 (from data-file) = $variable1"
    echo "variable3 (from data-file) = $variable3"
    
    let "sum = $variable2 + $variable4"
    echo "Sum of variable2 + variable4 (from data-file) = $sum"
    echo "message1 (from data-file) is \"$message1\""
    exit 0
    

    运行结果如下所示:

    $ sh kkk
    variable1 (from data-file) = 22
    variable3 (from data-file) = 5
    Sum of variable2 + variable4 (from data-file) = 571
    message1 (from data-file) is “Hello, how are you?”
    -n This
    -n
    -n is
    -n
    -n the
    -n
    -n message-print
    -n
    -n function
    -n
    -n in
    -n
    -n the
    -n
    -n data-file.
    -n

  7. ,:逗号操作符用于连接一连串的数学表达式。这一串的数学表达式每一个都被求值,但只有最后一个被返回。例如:

    let "t2 = ((a = 9, 15 / 3))"  # Set "a = 9" and "t2 = 15 / 3"
    
  8. \:用于单个字符的引用机制。\X"转义"字符为X

  9. /:分隔一个文件路径的各个部分。例如:/home/bozo/projects/Makefile

  10. `:(由于这个符号比较特殊我就直接用这种方式表示了)将会重新分配一个命令甚至是多个命令的输出;它会将命令的输出如实地添加到另一个上下文中。例如:

    #!/bin/bash
    textfile_listing=`ls *`
    echo "$textfile_listing"
    

    运行结果如下所示(下面都是当前目录下的文件):

    $ sh commandchange
    bbb
    commandchange
    kkk
    string

  11. ::这个命令意思是空操作(即什么操作也不做). 它一般被认为是和shell的内建命令true是一样的。冒号":" 命令是Bash自身内建的, and its它的退出状态码是真(即0)。例如:

    if condition
    then :   # 什么也不做的分支
    else
       take-some-action
    fi
    

    :的特殊使用方法如下所示:

     #!/bin/bash
     # 用10种不同的方法计数到11.
     n=1; echo -n "$n "
     
     let "n = $n + 1"   # let "n = n + 1"也可以.
     echo -n "$n "
      
     :$((n = $n + 1))
     #  ":"是需要的,
     #+ 否则Bash会尝试把"$((n = $n + 1))"作为命令运行.
     echo -n "$n "
     
     (( n = n + 1 ))
     #  上面是更简单的可行的办法.
     echo -n "$n "
     
     n=$(($n + 1))
     echo -n "$n "
     
     : $[ n = $n + 1 ]
     #  ":"是需要的,
     #+ 否则Bash会尝试把"$[ n = $n + 1 ]"作为命令运行.
     #  即使"n"被当作字符串来初始化也能工作.
     echo -n "$n "
     
     n=$[ $n + 1 ]
     #  即使"n"被当作字符串来初始化也能工作.
     #* 应避免这种使用这种结构,因为它是被废弃并不可移植的.
     echo -n "$n "
     
     # 现在是C风格的增加操作.
     # 多谢Frank Wang指出这一点.
     
     let "n++"          # let "++n"也可以.
     echo -n "$n "
     
     (( n++ ))          # (( ++n )也可以.
     echo -n "$n "
     
     : $(( n++ ))       # : $(( ++n ))也可以.
     echo -n "$n "
     
     : $[ n++ ]         # : $[ ++n ]]也可以.
     echo -n "$n "
     echo
     
     exit 0
    

    运算结果如下所示:

    $ sh compoperater
    -n 1
    -n 2
    -n 3
    -n 4
    -n 5
    -n 6
    -n 7
    -n 8
    -n 9
    -n 10
    -n 11

  12. !:取反一个测试结果或退出状态。

  13. *:星号(*)字符在用于匹配文件名扩展的一个通配符,它自动匹配给定的目录下的每一个文件。 在计算时,星号*表示乘法运算符。两个星号**表示求幂运算符。

  14. ?:字符?被用于文件名扩展特性的文件名表达式的单字符匹配,同时也在扩展正则表达式中匹配任意一个字符。

  15. $:变量替换 (引用一个变量的内容)。

    var1=5
    var2=23skidoo
    
    echo $var1     # 5
    echo $var2     # 23skidoo
    
  16. &:在后台运行作业。 一个后面跟一个&的命令会在后台运行。

  17. |:管道。把上一个命令的输出传给下一个命令,或是shell。这是连接命令的一种方法。

  18. $?:保存退出码值的变量. 变量$?保存了一个命令,一个函数,或一个脚本的退出状态码的值。

  19. $*, $@:位置参数。

  20. ${}:参数替换。

  21. ():命令组。一组由圆括号括起来的命令是新开一个子shell来执行的。因为是在子shell里执行,在圆括号里的变量不能被脚本的其他部分访问。因为父进程(即脚本进程)不能存取子进程(即子shell)创建的变量。例如:

    a=123
    ( a=321; )	       
    echo "a = $a"   # a = 123
    # 在圆括号里的变量"a"实际上是一个局部变量,作用局域只是在圆括号内用于数组始初化
    
  22. {}:这个结构也是一组命令代码块,事实上,它是匿名的函数。然而与一个函数所不同的,在代码块里的变量仍然能被脚本后面的代码访问。例如:

       1 #!/bin/bash
       2 # rpm-check.sh
       3 
       4 # 查询一个rpm安装包的描述,软件清单,和是否它能够被安装.
       5 # 并把结果保存到一个文件中.
       6 # 
       7 # 这个脚本使用一个代码块来举例说明。
       8 
       9 SUCCESS=0
      10 E_NOARGS=65
      11 
      12 if [ -z "$1" ]
      13 then
      14   echo "Usage: `basename $0` rpm-file"
      15   exit $E_NOARGS
      16 fi  
      17 
      18 { 
      19   echo
      20   echo "Archive Description:"
      21   rpm -qpi $1       # 查询软件包的描述.
      22   echo
      23   echo "Archive Listing:"
      24   rpm -qpl $1       # 查询软件包中的软件清单.
      25   echo
      26   rpm -i --test $1  # 查询该软件包能否被安装.
      27   if [ "$?" -eq $SUCCESS ]
      28   then
      29     echo "$1 can be installed."
      30   else
      31     echo "$1 cannot be installed."
      32   fi  
      33   echo
      34 } > "$1.test"       # 把代码块的所有输出重定向到一个文件中。
      35 
      36 echo "Results of rpm test in file $1.test"
      37 
      38 # 参考rpm的man手册来理解上面所用的选项。
      39 
      40 exit 0
    
  23. > &> >& >> <

    • sciptname >filename:重定向scriptname的输出到文件filename中去。如果文件filename存在则将会被覆盖。
    • command &>filename:会重定向命令command标准输出(stdout)和标准错误(stderr)到文件filename中。
    • command >&2:把命令command的标准输出(stdout)重定向到标准错误(stderr)。
    • scriptname >>filename:appends把脚本scriptname的输出追加到文件filename。如果filename不存在,则它会被创建。
  24. -:先前的工作目录。 命令cd -可以回到原来的工作目录.它使用了$OLDPWD 环境变量。

  25. ~+:当前工作目录。它与外部变量$PWD是一致的。

  26. ~-:先前的工作目录。它与外部变量$OLDPWD是一致的。

以上即为常见的特殊字符,可更有利于运用特殊字符来简化脚本编程。

参考资料


  1. SHELL脚本-第一课 ↩︎

发布了15 篇原创文章 · 获赞 0 · 访问量 346

猜你喜欢

转载自blog.csdn.net/u011228324/article/details/103869650