|
最简单的例子
用 vi 编辑器编辑一个 hello 文件如下:
#!/bin/bash
# This is a very simple example
echo Hello World
一,第一行的 #! 是什么意思
是说明 hello 这个文件的类型的,有点类似于 Windows 系统下用不同文件后缀来表示不同文件类型的意思(但不相同)
二,第一行的 /bin/bash 又是什么意思
后面的 "/bin/bash" 就表明该文件是一个 BASH 程序
三,第二行是注释吗
就是 BASH 程序的注释
四,echo 语句
echo 语句的功能是把 echo 后面的字符串输出到标准输出中去
五,如何执行该程序
BASH 程序被执行后,实际上 Linux 系统是另外开设了一个进程来运行的。
如何执行该程序呢?有两种方法:一种是显式制定 BASH 去执行:
bash hello或 sh hello (这里 sh 是指向 bash 的一个链接)
关于输入、输出和错误输出
在字符终端环境中,标准输入/标准输出的概念很好理解。输入即指对一个应用程序 或命令的输入,无论是从键盘输入还是从别的文件输入;输出即指应用程序或命令产生的一些信息;与 Windows 系统下不同的是,Linux 系统下还有一个标准错误输出的概念,这个概念主要是为程序调试和系统维护目的而设置的,错误输出和标准输出分开可以让一些高级的错误信息不干扰正常的输出 信息,从而方便一般用户的使用。
在 Linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。在 BASH 中使用这些概念时一般将标准输出表示为 1,将标准错误输出表示为 2。下面我们举例来说明如何使用他们,特别是标准输出和标准错误输出。
BASH 中对变量的规定(与 C 语言的异同)
在 BASH 中变量定义是不需要的,没有 "int i" 这样的定义过程。如果想用一个变量,只要他没有在前面被定义过,就直接可以用,当然你使用该变量的第一条语句应该是对他赋初值了,如果你不赋初值也没关 系,只不过该变量是空( 注意:是 NULL,不是 0 )。不给变量赋初值虽然语法上不反对,但不是一个好的编程习惯。好了我们看看下面的例子:
首先用 vi 编辑下面这个文件 hello2:
#!/bin/bash
# give the initialize value to STR
STR="Hello World"
echo $STR
整数变量和字符串变量各不相同,详见下表:
对应的操作 | 整数操作 | 字符串操作 | 相同 | -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 更老 |
BASH 中,在变量首次被赋初值时加上 local 关键字就可以声明一个局部变量,如下面这个例子:
#!/bin/bash
HELLO=Hello
function hello{
local HELLO=World
echo $HELLO
}
echo $HELLO
hello
echo $HELLO
该程序的执行结果是:
Hello
World
Hello
BASH 中的变量与 C 语言中变量的区别
这里我们为原来不熟悉 BASH 编程,但是非常熟悉 C 语言的程序员总结一下在 BASH 环境中使用变量需要注意的问题。
1,BASH 中的变量在引用时都需要在变量前加上$符号(第一次赋值及在For循环的头部不用加$符号);
2,BASH 中没有浮点运算,因此也就没有浮点类型的变量可用;
3,BASH 中的整形变量的比较符号与 C 语言中完全不同,而且整形变量的算术运算也需要经过 let 或 expr 语句来处理;
BASH 中的基本流程控制语法
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 循环结构与 C 语言中有所不同,在 BASH 中 for 循环的基本结构是:
for $var in
do
statments
done
其中 $var 是循环控制变量,
是 var需要遍历的一个集合,do/done对包含了循环体,相当于C语言中的一对大括号。另外如果do和for被写在同一行,必须在do前面加上";"。如:forvar in ; do 。下面是一个运用 for 进行循环的例子:
#!/bin/bash
for day in Sun Mon Tue Wed Thu Fri Sat
do
echo day
done
exit 0
# 如果列表被包含在一对双引号中,则被认为是一个元素
for day in "Sun Mon Tue Wed Thu Fri Sat"
do echo day
done
exit 0
注意上面的例子中,在 for 所在那行的变量 day 是没有加 ""符号的,而在循环体内,echo所在行变量day 是必须加上 "$" 符号的。另外如果写成 for day 而没有后面的 in部分,则 day 将取遍命令行的所有参数。如这个程序:
#!/bin/bash
for param
do
echo $param
done
exit 0
上面这个程序将列出所有命令行参数。for 循环结构的循环体被包含在 do/done 对中,这也是后面的 while、until 循环所具有的特点。
while
while 循环的基本结构是:
while [ condition ]
do
statments
done
这个结构请大家自己编写一个例子来验证。
2.4.4 until
until 循环的基本结构是:
until [ condition is TRUE ]
do
statments
done
这个结构也请大家自己编写一个例子来验证。
case
BASH 中的 case 结构与 C 语言中的 switch 语句的功能比较类似,可以用于进行多项分支控制。其基本结构是:
case "$var" in
condition1 )
statments1;;
condition2 )
statments2;;
...
* )
default statments;;
esac
下面这个程序是运用 case 结构进行分支执行的例子:
#!/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 语句表示从键盘上读取输入。这个命令将在本讲义的 BASH 的其他高级问题中讲解。
break/continue
熟悉 C 语言编程的都很熟悉 break 语句和 continue 语句。BASH 中同样有这两条语句,而且作用和用法也和 C 语言中相同,break 语句可以让程序流程从当前循环体中完全跳出,而 continue 语句可以跳过当次循环的剩余部分并直接进入下一次循环。
函数的使用
BASH 是一个相对简单的脚本语言,不过为了方便结构化的设计,BASH 中也提供了函数定义的功能。BASH 中的函数定义很简单,只要向下面这样写就可以了:
function my_funcname {
code block
}
或者
my_funcname() {
code block
}
上面的第二种写法更接近于 C 语言中的写法。BASH 中要求函数的定义必须在函数使用之前,这是和 C 语言用头文件说明函数方法的不同。
更进一步的问题是如何给函数传递参数和获得返回值。BASH 中函数参数的定义并不需要在函数定义处就制定,而只需要在函数被调用时用 BASH 的保留变量 12 ... 来引用就可以了;BASH 的返回值可以用 return 语句来指定返回一个特定的整数,如果没有 return 语句显式的返回一个返回值,则返回值就是该函数最后一条语句执行的结果(一般为 0,如果执行失败返回错误码)。函数的返回值在调用该函数的程序体中通过 $? 保留字来获得。下面我们就来看一个用函数来计算整数平方的例子:
#!/bin/bash
demoFunc(){
let "res=1+1"
return $res
}
demoFunc
result=$?
echo $result
exit 0
保留变量
BASH 中有一些保留变量,下面列出了一些:
IFS 这个变量中保存了用于分割输入参数的分割字符,默认识空格。HOME 这个变量中存储了当前用户的根目录路径。
PATH 这个变量中存储了当前Shell的默认路径字符串。PS1 表示第一个系统提示符。
PS2 表示的二个系统提示符。PWD 表示当前工作路径。
EDITOR表示系统的默认编辑器名称。BASH 表示当前 Shell 的路径字符串。
0,1, 2,...表示系统传给脚本程序或脚本程序传给函数的第0个、第一个、第二个等参数。# 表示脚本程序的命令参数个数或函数的参数个数。
$$ 表示该脚本程序的进程号,常用于生成文件名唯一的临时文件。
? 表示脚本程序或函数的返回状态值,正常为0,否则为非零的错误号。* 表示所有的脚本参数或函数参数。
@ 和* 涵义相似,但是比 ∗更安全。! 表示最近一个在后台运行的进程的进程号。
随机数
随机数是经常要用到的,BASH 中也提供了这个功能,请看下面这个程序:
#!/bin/bash
# Prints different random integer from 1 to 65536
a=RANDOMechoa
exit 0
这个程序可以在每次执行的时候随机的打印出一个大小在 1 到 65536 之间的整数。
运算符
算术运算符
+ - * / % 表示加减乘除和取余运算
+= -= *= /= 同 C 语言中的含义
位操作符
<< <<= >> >>= 表示位左右移一位操作
& &= | |= 表示按位与、位或操作
~ ! 表示非操作
^ ^= 表示异或操作
关系运算符
< > <= >= == != 表示大于、小于、大于等于、小于等于、等于、不等于操作
&& || 逻辑与、逻辑或操作
变量的特殊操作
BASH 中还有一些对变量的简洁、快速的操作,大家还记得 "var"和"var" 同样是对变量的引用吧,对 var进行一些变化就可以产生一些新功能:{var-default} 表示如果变量 var还没有设置,则保持var 没有设置的状态,并返回后面的默认值 default。
var=default表示如果变量var 还没有设置,则取后面的默认值 default。
var+otherwise表示如果变量var 已经设置,则返回 otherwise 的值,否则返回空( null )。
var?errmsg表示如果变量var 已经设置,则返回该变量的值,否则将后面的 err_msg 输出到标准错误输出上。
请同学们自己尝试下面的例子:
#!/bin/bash
echo ${var?There is an error}
exit 0
还有下面一些用法,这些用法主要用于从文件路径字符串中提取有用信息:
{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 字符串。
|
|