alenchan amanda apache ……
举例4:接下来我们以交互式实现循环功能,即当我们输入y或Y时,程序就结束。可以这样做:
# vi test15-loop.sh
#!/bin/bash #Using until #xag 2007-4-12
echo \
until [ \do
read yn done
echo \# sh test15-loop.sh Press Y/y to stop //下面的几行除了Stop here之外,都是你自己随意输入的内容: GDSG A Y
Stop here
上面说的是,当输入Y或y时才跳出do…done循环,而去执行下面的东西。
举例5:接下来,我们来判断目录是否存在,这是常用的。看看所谓的逻辑判断式的使用方法。可以使用条件判断来断定到底有没有文件(用-e)或者该名称是属于目录还是文件(-d,-f),接下来我们判断一个流程:
(1) 先查看~/test/logical这个名称是否存在; (2) 若不存在,则使用touch建立一个文件,建立完成后退出; (3) 如果存在,判断该名称是否为文件,若为文件则将之删除后建立一个目录,
文件名为logical,之后退出; (4) 如果存在,而且该名称为目录,则移除此目录。 看起来似乎很复杂,其实很简单。如下: # vi test16-ifthen.sh
#!/bin/bash
#Using if and then to select file or directory #xag 2007-4-12
if [ ! –e logical ];then touch logical
echo \
elif [ -e logical ] && [ -f logical ];then rm logical mkdir logical
echo \
echo \
- 31 -
exit 1
elif [ -e logical ] && [ -d logical ];then rm -rf logical
echo \else
echo \fi
然后请你依次执行sh test16-ifthen.sh ; ll 看看这个目录下logical文件有什么变化。这个动作可以让我们很轻松地判别出某个文件是否存在。
8. 如何调试脚本
脚本在执行之前,最怕的就是出现问题,那么如何调试脚本?有没有办法不需要直接执行该脚本就可以判断是否有问题?当然有,我们就直接以sh进行判断。 sh语法格式:sh [-nvx] scripts
-n:不执行脚本,查询脚本内的语法,若有错误则列出 -v:在执行脚本之前,先将脚本的内容显示在屏幕上; -x:将用到的脚本内容显示在屏幕上,与-v稍微不同。 如:
# sh -n test01-hello.sh # sh -v test01-hello.sh #!/bin/bash
#这个脚本的用途在屏幕上显示Hello ! How are you #创建日期:2007-4-10 #Written by xag
hello=Hello\\\\!\\How\\are\\you\\\\? echo $hello
Hello ! How are you
# sh –x test01-hello.sh + hello=Hello ! How are you + echo 'Hello !' How are you Hello ! How are you
熟悉sh的用法,可以使你在管理Linux的过程中得心应手。
对于Shell Scripts的学习方法,需要多看、多模仿,并将其修改为已用,这是最快的学习手段。网上有很多人在开发一些很有用的脚本,可以将对方的脚本拿来,并且改成适合自己主机的脚本,那么学习效果会更好。
四、练习:
请将本实验中的各个例子上机实验。
实验六 Linux编程环境
一、实验目的:
1. 掌握简单文件编辑器Vi等的使用 2. 掌握gcc编译器的使用
- 32 -
3. 掌握gdb调试C程序
二、实验环境:
1. 计算机实验室单机环境下的Linux 2. 计算机实验室Windows下远程登录
三、学习过程与实验内容
1. Vi的使用,见实验三。或者学习其他的文本编辑器如emacs(见课件) 2. 使用GNU cc
GNU cc(gcc)是Gnu/Linux操作系统中编译器套件,使用它能够编译C等编写的程序。gcc是一个交叉平台的编译器,支持在不同CPU平台上开发基于不同体系结构硬件的软件。gcc也可以在编译时优化执行代码,而且能够产生调试代码。
gcc在编辑过程中可以分为预处理、编译、链接三个阶段。 下表说明了gcc常用命令行选项 选项 -o filename -c -DFOO=BAR -IDIRNAME -LDIRNAME -static -lFOO -g -ggdb -On -ansi -pedantic -pedantic –error -w -Wall -werror -v 描述 指定输出文件名,如果不指定filename缺省文件则是a.out 只编译产生目标文件(.o文件)不链接 定义预处理宏FOO,其值为BAR 将DIRNAME路径加到头文件搜索目录中 将DIRNAME路径加到库文件搜索目录中 静态链接库文件 链接名为libFOO的库文件 在可执行代码中包含标准的调试信息 在可执行代码中包含gdb特有的调试信息 指定优化编译的级别n,n可以为1、2、3 使用ANSI/ISO C标准语法 允许发出ANSI/ISO C标准所列出的警告 允许发出ANSI/ISO C标准所列出的错误 关闭所有警告 允许发出gcc的所有警告 编译时将警告作为错误处理 显示在编译过程中每一步用到的命令 (1)举例:简单使用(源程序名设为t1.c)
1) 直接编译成可执行文件t1 #gcc t1.c –o t1 2) 只做预处理
#gcc -E t1.c –o t1.cpp
3) 将预处理结果编译成目标文件 #gcc -x cpp-output -c t1.cpp 4) 将目标文件链接成可执行文件t1 #gcc t1.o -o t1 (2)优化编译选项
优化可以改进执行文件的代码长度和执行效率 -O1 通常包括线程直接跳转和延迟退栈。
-O2 包含O1级所做的优化,并调整处理器指令执行时序。优化使处理器在等待其他指令的结果或数据延迟时仍然可以执行其他不相关指令,从而充分利用CPU资源,但
- 33 -
其实现与处理器是密切相关的
-O3 包括O2级的一切优化并使用内嵌函数、循环展开以及其他与特定处理器特性有关的优化。 (3)调试选项
gcc能够使用-g和-ggdb选项在可执行代码中插入调试信息以便于程序调试。-g选项后可以附加1、2或3指定要在代码中加入多少调试信息。缺少情况下是2,它将在输出代码中加入符号表、行号、局部和外部变量信息。1级选项仅生成函数调用时的堆栈转储和回退信息,不包含行号和变量的调试信息。3级选项则包括所有2级的调试信息并包含所有宏定义等。
如果使用GNU Debugger(gdb)来调试,可以使用-ggdb所特有的调试信息以方便gdb调试。但是,这样做会使程序不能被其他的调试程序调试。 3. 使用GNU gdb
一般,Linux发行版本都包含了一个叫gdb的GNU调试程序。gdb是一个功能强劲的调试器,提供了非常复杂的调试功能: ? 在调试器中查看代码 ? 设置断点
? 单步执行跟踪监视程序中变量的值 ? 运行中改变程序代码 (1) 启动gdb
#gdb
或#gdb filename //filename是由gcc –g(或-ggdb)生成的含调试信息的可执行文件 如下例:
#gcc -g t1.c -o t1 #gdb t1
(2) 在调试中查看源代码
(gdb)list //在gdb命令提示符下输入list命令显示当前行附件的10行代码
或(gdb) list n //显示第n行附近10行代码 (3) 设置断点与单步执行
(gdb)break
或在上面两种方式中加上文件名如break <文件名:n>来实现一个多文件项目设置断点 或(gdb)break <行号n或函数名> if <条件表达式> //根据条件设置断点
在断点停止执行时,可以用step或next命令实现单步调试,step遇到函数时将单步进入函数,而next命令在遇到函数时执行整个函数。 (4) 监视程序中变量的值
(gdb)print 变量名
第一次显示为$1=值 第二次显示出为$2=值等等 (5) 改变代码的运行
(gdb)print 变量名=值 //可以用print命令给变量在调试中赋新值,方便调试 可以用finish命令结束当前函数的调用(含main函数),或者用return value停止当前函数并将value返回结调用者。 4. 练习
如有以下C程序yanghui.c #include
- 34 -
int main()
{ int a[16][16]; int i,j;
for(i=1;i<16;i++)
{a[i][1]=1;a[i][i]=1;} for(i=3;i<16;i++) for(j=2;j
a[i][j]=a[i-1][j-1]+a[i-1][j]; for(i=1;i<16;i++) { for(j=1;j<=i;j++)
printf(\ printf(\ } }
(1) 用gcc编译生成可执行文件yanghui?
(2) 用gcc只做预处理生成yanghui.cpp?
(3) 将yanghui.cpp编译生成目标文件yanghui.o?
(4) 再yanghui.o链接生成yanghui1
(5) 为了使用gdb来调试,请将yanghui.c编译生成含调试信息的目标代码文件yanghui2。
(6) 用gdb打开yanghui2文件,用list命令查看一下源代码。
(7) 在gdb环境下运行代码查看输出结果。
(8) 将第7行设置一个断点,并使程序运行,到第7行暂停,此时查看i,j变量的值为
何?用whatis命令查看变量i,j的类型及数据a的类型。
(9) 使用单步命令执行5次后,查看此时i,j的值为何?
(10) 再将第15行设置第二个断点?使程序从刚才位置直接运行到此断点。(finish)
(11) 删除所有断点,再运行一次程序。
(12) 修改源程序yanghui.c将第10行修改为for(i= =1;i<16;i++),再将其编译生成含调试
信息的目标代码yanghui3。
(13) 在gdb中打开yanghui3,运行,查看结果是什么?为什么?
(14) 将第10行设置成断点,运行程序,暂停后查看i的值,结果为多少?
(15) 此时,用print语句将i设置成1,再单步查看程序的执行,是否可以继续执行?为
- 35 -