一直都想学习好脚本,可是总是没有认认真真地学过。 这几天看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形式的标记法(有范围和符号限制).
阅读(657) | 评论(0) | 转发(0) |