回顾
- shell脚本编程的不适用场景的列举;1
- 简单的shell脚本展示;
- 解释器说明及注意事项;
- 脚本的运行方式。
基础知识
在此,我们将对一些特殊字符,变量命名及常见使用方式做一些介绍,以便你做基本的了解。首先,我们来看看看有哪些特殊的字符值得注意。
特殊字符
脚本中常常会出现一些特殊的字符,他们都表示一些特定的含义,我们接下来对它们做一一的介绍。
-
#
:以一个#开头的行 (#!是例外) 是注释行。例如:#这是一行注释.
-
;
:【命令分割符】用分割符允许在同一行里有两个或更多的命令。例如: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."
-
;;
:case语句分支的结束符[双分号]。例如:case "$variable" in abc) echo "\$variable = abc" ;; xyz) echo "\$variable = xyz" ;; esac
-
'
:'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从运行结果可以看出,在单引号中的变量引用会被禁止,字符
$
会仅仅被认为是一个普通的字符,而不是变量的前缀。 -
"
:"STRING"的引用会使STRING里的特殊字符能够被解释。其中例子如上所示。 -
.
:等同于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 -
,
:逗号操作符用于连接一连串的数学表达式。这一串的数学表达式每一个都被求值,但只有最后一个被返回。例如:let "t2 = ((a = 9, 15 / 3))" # Set "a = 9" and "t2 = 15 / 3"
-
\
:用于单个字符的引用机制。\X
"转义"字符为X
。 -
/
:分隔一个文件路径的各个部分。例如:/home/bozo/projects/Makefile
。 -
`:(由于这个符号比较特殊我就直接用这种方式表示了)将会重新分配一个命令甚至是多个命令的输出;它会将命令的输出如实地添加到另一个上下文中。例如:
#!/bin/bash textfile_listing=`ls *` echo "$textfile_listing"
运行结果如下所示(下面都是当前目录下的文件):
$ sh commandchange
bbb
commandchange
kkk
string -
:
:这个命令意思是空操作(即什么操作也不做). 它一般被认为是和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 -
!
:取反一个测试结果或退出状态。 -
*
:星号(*)字符在用于匹配文件名扩展的一个通配符,它自动匹配给定的目录下的每一个文件。 在计算时,星号*
表示乘法运算符。两个星号**
表示求幂运算符。 -
?
:字符?被用于文件名扩展特性的文件名表达式的单字符匹配,同时也在扩展正则表达式中匹配任意一个字符。 -
$
:变量替换 (引用一个变量的内容)。var1=5 var2=23skidoo echo $var1 # 5 echo $var2 # 23skidoo
-
&
:在后台运行作业。 一个后面跟一个&
的命令会在后台运行。 -
|
:管道。把上一个命令的输出传给下一个命令,或是shell。这是连接命令的一种方法。 -
$?
:保存退出码值的变量. 变量$?保存了一个命令,一个函数,或一个脚本的退出状态码的值。 -
$*, $@
:位置参数。 -
${}
:参数替换。 -
()
:命令组。一组由圆括号括起来的命令是新开一个子shell来执行的。因为是在子shell里执行,在圆括号里的变量不能被脚本的其他部分访问。因为父进程(即脚本进程)不能存取子进程(即子shell)创建的变量。例如:a=123 ( a=321; ) echo "a = $a" # a = 123 # 在圆括号里的变量"a"实际上是一个局部变量,作用局域只是在圆括号内用于数组始初化
-
{}
:这个结构也是一组命令代码块,事实上,它是匿名的函数。然而与一个函数所不同的,在代码块里的变量仍然能被脚本后面的代码访问。例如: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
-
> &> >& >> <
:sciptname >filename
:重定向scriptname的输出到文件filename中去。如果文件filename存在则将会被覆盖。command &>filename
:会重定向命令command标准输出(stdout)和标准错误(stderr)到文件filename中。command >&2
:把命令command的标准输出(stdout)重定向到标准错误(stderr)。scriptname >>filename
:appends把脚本scriptname的输出追加到文件filename。如果filename不存在,则它会被创建。
-
-
:先前的工作目录。 命令cd -
可以回到原来的工作目录.它使用了$OLDPWD
环境变量。 -
~+
:当前工作目录。它与外部变量$PWD
是一致的。 -
~-
:先前的工作目录。它与外部变量$OLDPWD
是一致的。
以上即为常见的特殊字符,可更有利于运用特殊字符来简化脚本编程。