shell脚本的本质
shell脚本语言是解释型语言
shell脚本的本质:shell命令的有序集合
shell编程的基本过程
-
建立shell文件——包含任意多行操作系统命令或shell命令的文本文件;
-
赋予shell文件执行权限——用chmod命令修改权限;
-
执行shell文件——直接在命令行上调用shell程序;
shell变量
shell允许用户建立变量存储数据,但不支持数据类型(整形、字符、浮点型),将任何赋给变量的值都解释为一串字符
Bourne Shell有如下四种变量:
-
用户自定义变量
-
位置变量即命令行参数
-
预定义变量
-
环境变量
用户自定义变量
在shell编程中通常使用全大写变量,方便识别
$COUNT=1
变量调用:在变量前加$
$echo $HOME
使用unset命令删除变量的赋值
$unset COUNT
shell程序和语句
shell程序由零或多条shell语句构成。shell语句包括三大类:说明性语句、功能性语句和结构性语句
说明性语句:以#号开始到该行结束,不被解释执行
功能性语句:任意shell命令、用户程序或其它shell程序
结构性语句:条件测试语句、多路分支语句、循环语句、循环控制语句等
expr命令
算术运算命令expr主要用于进行简单的整数运算,包括加+、减-、乘\*
、除/、求模%等操作。
test语句
test语句可测试三种对象:字符串 整数 文件属性
每种测试对象都有若干测试操作符
字符串测试
s1 = s2 | 测试两个字符串的内容是否完全一样 |
---|---|
s1 != s2 | 测试两个字符串的内容是否有差异 |
-z s1 | 测试s1字符串的长度是否为0 |
-n s1 | 测试s1字符串的长度是否不为0 |
整数测试
a -eq b | 测试a与b是否相等 |
---|---|
a -ne b | 测试a与b是否不相等 |
a -gt b | 测试a是否大于b |
a -ge b | 测试a是否大于等于b |
a -lt b | 测试a是否小于b |
a -le b | 测试a是否小于等于b |
文件测试
-d name | 测试name是否为一个目录 |
---|---|
-e name | 测试一个文件是否存在 |
-f name | 测试name是否为普通文件 |
-L name | 测试name是否为符号链接 |
-r name | 测试name文件是否存在且为可读 |
-w name | 测试name文件是否存在且为可写 |
-x name | 测试name文件是否存在且为可执行 |
-s name | 测试name文件是否存在且其长度不为0 |
f1 -nt f2 | 测试文件f1是否比文件f2更新 |
f1 -ot f2 | 测试文件f1是否比文件f2更旧 |
结果:
结构性语句
结构性语句主要根据程序的运行状态、输入数据、变量的取值、控制信号以及运行时间等因素来控制程序的运行流程。
主要包括:条件测试语句、多路分支语句、循环语句、循环控制语句和后台执行语句等。
条件语句
if [ 表达式]
then 命令表
fi
如果表达式为真,则执行命令表中的命令;否则执行fi后面的语句。if和fi是条件语句的括号语句,必须成对使用;命令表中的命令可以是一条,也可以是多条。
if 表达式
then 命令表1
else 命令表2
fi
如果表达式为真,则执行命令表1中的命令,再退出if语句;否则执行命令表2中的语句,再退出if语句。
多路分支语句
case 字符串变量 in
模式1)
命令表1
;;
模式2 | 模式3)
命令表2
;;
.......
模式n)
命令表n
;;
esac
编写一个shell脚本来判断成绩的等级
#!/bin/bash
echo -n "Please input score:"
read S
if [ $S -lt 0 -o $S -gt 100 ]
then
echo "not in [0-100]"
exit
fi
G=`expr $S / 10`
case $G in
9|10)
echo "$S A"
;;
6|7|8)
echo "$S B"
;;
*)
echo "$S C"
esac
结果:
循环语句for
当循环次数已知或确定时,使用for循环语句来多次执行一条或一组命令。循环体由语句括号do和done来限定。
for 变量名 in 单词表
do
命令表
done
变量依次取单词表中的各个单词,每取一次单词,就执行一次循环体中的命令,循环次数由单词表中的单词数确定。命令表中的命令可以是一条,也可以是由分号或换行符分开的多条。
#!/bin/bash
sum=0
for i in `seq 1 100`
do
sum=`expr $sum + $i`
done
echo $sum
for ((i=1;i<=10;i++))
do
echo $i
done
结果:
循环语句
while 命令或表达式
do
命令表
done
while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。
while语句的退出状态为命令表中被执行的最后一条命令的退出状态。
shell函数调用
value_name=`function_name [arg1 arg2 ... ]`
function_name [arg1 arg2 .. ]
echo $?
函数变量作用域
全局作用域:在脚本的其他任何地方都能够访问该变量
局部作用域:只能在声明变量的作用域内访问。
声明局部变量的格式:
Local variable_name =value
GNU工具
编译工具:把一个源程序编译为一个可执行程序
调试工具:能对执行程序进行源码或汇编级调试
软件工程工具:用于协助多人开发或大型软件项目的管理
其他工具:用于把多个目标文件链接成可执行文件的链接器,或者用作格式转换的工具
GCC简介
全称为GNU CC,GNU项目中符合ANSI C标准的编译系统
编译如C、C++、Object C、Java、Fortran、Pascal、Modula-3和Ada等多种语言
GCC是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%
一个交叉平台编译器,适合在嵌入式领域的开发编译
编译器的主要组件
分析器
汇编器
链接器
标准C库
GCC的基本用法和选项
-c | 只编译,不连接成为可执行文件.c到.o |
---|---|
-o | 确定输出文件的名称 |
-g | 产生符号调试工具(gdb) |
-O | 对程序进行优化编译、连接 |
-O2 | 比-o更好的优化编译、连接 |
-I dirname | 将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数 |
-L dirname | 将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数。 |
GCC的错误
-
语法错误(syntex error)
-
头文件错误(Can no find include file head.h)
-
档案库错误(ld: -lm: No such file or directory)
-
未定义符号(Undefined symbol)
GCC编译过程
-
预处理(Pre-Processing)
-
编译(Compiling)
-
汇编(Assembling)
-
链接(Linking)
生成预处理代码
$gcc -E test.c -o test.i
生成汇编代码
$gcc -S test.i -o test.s
生成目标代码
$gcc -c test.s -o test.o
$as test.s -o test.o
生成可执行程序
将目标程序链接库资源,生成可执行程序
gcc test.s -o test
./test
调试器——gdb
首先使用gcc对test.c进行编译,注意一定要加选项‘-g’
$gcc -g test.c -o test
gdb test
(gdb) l | 查看文件 |
---|---|
(gdb) b 6 | 设置断点 |
(gdb) info b | 查看断点情况 |
(gdb) r | 运行代码 |
(gdb) p n | 查看变量值 |
(gdb) n /(gdb) s | 单步运行 |
(gdb) c | 恢复程序运行 |
(gdb) help [command] | 帮助 |
Gdb的使用切记点
在gcc编译选项中一定要加入’-g’
只有在代码处于“运行”或“暂停”状态时才能查看变量值
设置断点后程序在指定行之前停止