shell的种类:
sh - Bourne shell
csh or tcsh - C shell
korn - Korn shell
bash - GNU Bourne-Again shell
1.最简单的列子
例子
#!/bin/bash
# This is a very simple example echo Hello World
echo Hello World
解释:
在 BASH 中 第一行的 "#!" 及后面的 "/bin/bash" 就表明该文件是一个 BASH 程序,需要由 /bin 目录下的 bash 程序来解释执行。
在 BASH 程序中从“#”号(注意:后面紧接着是“!”号的除外)开始到行尾的多有部分均被看作是程序的注释
echo 语句的功能是把 echo 后面的字符串输出到标准输出中去
执行该程序:
1.$ bash hello 或
$ sh hello
2.将 hello 文件改为可以执行的文件,然后直接运行它,此时由于 hello 文件第一行的 "#! /bin/bash" 的作用,系统会自动用/bin/bash 程序去解释执行 hello 文件的:
$ chmod u+x hello
$ ./hello
2.关于输入、输出和错误输出
在 Linux 系统中:
标准输入(stdin)默认为键盘输入;
标准输出(stdout)默认为屏幕输出;
标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。
$ ls > ls_result
$ ls -l >> ls_result
ls 命令的结果输出
重定向到 ls_result 文件中和
追加到 ls_result 文件中,而不是输出到屏幕上。
">"就是输出(标准输出和标准错误输出)重定向的代表符号,连续两个 ">" 符号,即 ">>" 则表示不清除原来的而追加输出
$ find /home -name lost* 2> err_result
这个命令在 ">" 符号之前多了一个 "2","2>" 表示将标准错误输出重定向。由于 /home 目录下有些目录由于权限限制不能访问,因此会产生一些标准错误输出被存放在 err_result 文件中
$ find /home -name lost* > all_result 2>& 1
首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。这样我们就可以将所有的输出都存储到文件中了
更简单的写法:
$ find /home -name lost* >& all_result
可以让你避开众多无用出错信息的干扰:
$ find /home -name lost* 2> /dev/null
另外一个非常有用的重定向操作符是 "-"
$ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)
该命令表示把 /source/directory 目录下的所有文件通过压缩和解压,快速的全部移动到 /dest/directory 目录下去
3.变量
例子:
#!/bin/bash
# give the initialize value to
STR STR="Hello World"
echo $STR
注意点:
1,变量赋值时,'='左右两边都不能有空格;
2,BASH 中的语句结尾不需要分号(";");
3,除了在变量赋值和在FOR循环语句头中,BASH 中的变量使用必须在变量前加"$"符号,
4,由于 BASH 程序是在一个新的进程中运行的,所以该程序中的变量定义和赋值不会改变其他进程或原始 Shell 中同名变量的值,也不会影响他们的运行。
一个变量即可以被定义为一个字符串,也可以被再定义为整数。如果对该变量进行整数运算,他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串
例子:
#!/bin/bash
x=1999
let "x = $x + 1"
echo $x
x="olympic'"$x
echo $x
整数运算一般通过 let 和 expr 这两个指令来实现,如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1`
对应的操作
|
整数操作
|
字符串操作
|
相同
|
-eq
|
=
|
不同
|
-ne
|
!=
|
大于
|
-gt
|
>
|
小于
|
-lt
|
<
|
大于或等于
|
-ge
|
|
小于或等于
|
-le |
|
为空
|
|
-z
|
不为空
|
|
-n
|
BASH 中用于判断文件属性的操作符:
运算符
|
含义( 满足下面要求时返回 TRUE )
|
-e file
|
文件 file 已经存在
|
-f file
|
文件 file 是普通文件 |
-s file
|
文件 file 大小不为零
|
-d file
|
文件 file 是一个目录
|
-r file
|
文件 file 对当前用户可以读取
|
-w file
|
文件 file 对当前用户可以写入
|
-x file
|
文件 file 对当前用户可以执行
|
-g file
|
文件 file 的 GID 标志被设置
|
-u file
|
文件 file 的 UID 标志被设置
|
-O file
|
文件 file 是属于当前用户的
|
-G file
|
文件 file 的组 ID 和当前用户相同
|
file1 -nt file2
|
文件 file1 比 file2 更新
|
file1 -ot file2
|
文件 file1 比 file2 更老
|
局部变量
在变量首次被赋初值时加上 local 关键字就可以声明一个局部变量
例子:
#!/bin/bash
HELLO=Hello
function hello {
local HELLO=World
echo $HELLO
}
echo $HELLO
hello
echo $HELLO
该程序的执行结果是:
Hello
World
Hello
4.基本流程控制语法
if...then...else
if 语句用于判断和分支,其语法规则和 C 语言的 if 非常相似。其几种基本结构为:
if [ expression ]
then
statments
fi
或者==========================
if [ expression ]
then
statments
else
statments
fi
或者==========================
if [ expression ]
then
statments
else if [ expression ]
then
statments
else
statments
fi
或者==========================
if [ expression ]
then
statments
elif [ expression ]
then
statments
else
statments
fi
注:如果你将 if 和 then 简洁的写在一行里面,就必须在 then 前面加上分号,如:if [ expression ]; then ...
for循环
for $var in [list]
do
statments
done
注:do 和 for 被写在同一行,必须在 do 前面加上 ";"。如: for $var in [list]; do
例子:
#!/bin/bash
for day in Sun Mon Tue Wed Thu Fri Sat
do
echo $day
done
如果列表被包含在一对双引号中,则被认为是一个元素
例子:
#!/bin/bash
for day in “Sun Mon Tue Wed Thu Fri Sat “
do
echo $day
done
如果写成 for day 而没有后面的 in [list] 部分,则 day 将取遍命令行的所有参数
例子:
#!/bin/bash
for param
do
echo $param
done
exit 0
while
while [ condition ]
do
statments
done
util
until [ condition is TRUE ]
do
statments
done
case
case "$var" in
condition1 )
statments1;;
condition2 )
statments2;;
...
* )
default statments;;
esac
例子
#!/bin/bash
echo "Hit a key, then hit return."
read Keypress
case "$Keypress" in
[a-z] ) echo "Lowercase letter";;
[A-Z] ) echo "Uppercase letter";;
[0-9] ) echo "Digit";;
* ) echo "Punctuation, whitespace, or other";;
esac
exit 0
"read Keypress" 一句中的 read 语句表示从键盘上读取输入
支持break/continue
你懂得
5.函数
function my_funcname {
code block
}
或者
my_funcname() {
code block
}
BASH 中函数参数的定义并不需要在函数定义处就制定,而只需要在函数被调用时用 BASH 的保留变量 $1 $2 ... 来引用就可以了;
BASH 的返回值可以用 return 语句来指定返回一个特定的整数,如果没有 return 语句显式的返回一个返回值,则返回值就是该函数最后一条语句执行的结果(一般为 0,如果执行失败返回错误码)。
函数的返回值在调用该函数的程序体中通过 $? 保留字来获得。
例子
#!/bin/bash
square() {
let "res = $1 * $1"
return $res
}
square $1
result=$?
echo $result
exit 0
6.BASH 中的特殊保留字
保留变量
$IFS 这个变量中保存了用于分割输入参数的分割字符,默认是空格。
$HOME 这个变量中存储了当前用户的根目录路径。
$PATH 这个变量中存储了当前 Shell 的默认路径字符串。
$PS1 表示第一个系统提示符。
$PS2 表示的二个系统提示符。
$PWD 表示当前工作路径。
$EDITOR 表示系统的默认编辑器名称。
$BASH 表示当前 Shell 的路径字符串。
$0, $1, $2, ... 表示系统传给脚本程序或脚本程序传给函数的第0个、第一个、第二个等参数。
$# 表示脚本程序的命令参数个数或函数的参数个数。
$$ 表示该脚本程序的进程号,常用于生成文件名唯一的临时文件。
$? 表示脚本程序或函数的返回状态值,正常为 0,否则为非零的错误号。
$* 表示所有的脚本参数或函数参数。
$@ 和 $* 涵义相似,但是比 $* 更安全。
$! 表示最近一个在后台运行的进程的进程号。
$UID 用户uid $set |grep UID 获取
随机数
$RANDOM:随机产生一个大小在 1 到 65536 之间的整数。
变量的特殊操作
${var-default} 表示如果变量 $var 还没有设置,则保持 $var 没有设置的状态,并返回后面的默认值 default。
${var=default} 表示如果变量 $var 还没有设置,则取后面的默认值 default。
${var+otherwise} 表示如果变量 $var 已经设置,则返回 otherwise 的值,否则返回空( null )。
${var?err_msg} 表示如果变量 $var 已经设置,则返回该变量的值,否则将后面的 err_msg 输出到标准错误输出上。
这些用法主要用于从文件路径字符串中提取有用信息:
${var#pattern}, ${var##pattern} 用于从变量 $var 中剥去最短(最长)的和 pattern 相匹配的最左侧的串。
${var%pattern}, ${var%%pattern} 用于从变量 $var 中剥去最短(最长)的和 pattern 相匹配的最右侧的串。
另外 BASH 2 中还加入下面一些操作:
${var:pos} 表示去掉变量 $var 中前 pos 个字符。
${var:pos:len} 表示变量 $var 中去掉前 pos 个字符后的剩余字符串的前 len 个字符。
${var/pattern/replacement} 表示将变量 $var 中第一个出现的 pattern 模式替换为 replacement 字符串。
${var//pattern/replacement} 表示将变量 $var 中出现的所有 pattern 模式全部都替换为 replacment 字符串。
7.BASH 中的其他高级问题
BASH 中对返回值的处理
无论是在 Shell 中对 BASH 脚本返回值的处理,还是在脚本中对函数返回值的处理,都是通过 "$?" 系统变量来获得。
BASH 要求返回值必须为一个整数,不能用 return 语句返回字符串变量
用 BASH 设计简单用户界面
select var in [list]
do
statments use $var
done
BASH 会将 [list] 中的所有项加上数字列在屏幕上等待用户选择,在用户作出选择后,变量 $var 中就包含了那个被选中的字符串
例子
#!/bin/bash
OPTIONS="Hello Quit"
select opt in $OPTIONS; do
if [ "$opt" = "Quit" ]; then
echo done
exit
elif [ "$opt" = "Hello" ]; then
echo Hello World
else
clear
echo bad option
fi
done
exit 0
BASH 程序的调试
用 bash -x bash-script 命令,可以查看一个出错的 BASH 脚本到底错在什么地方,可以帮助程序员找出脚本中的错误。
另外用 trap 语句可以在 BASH 脚本出错退出时打印出一些变量的值,以供程序员检查。
trap 语句必须作为继 "#!/bin/bash" 后的第一句非注释代码,一般 trap 命令被写作: trap 'message $checkvar1 $checkvar2' EXIT