通过反复的编写、调试,基本上最终的脚本go.sh如下表所示:
由于SHELL脚本起源于上个世纪70、80年代,因此可读性比当前的编程语言一般要差一些,因此下面对这个脚本中的内容作一下简单的说明:[exam@Exam-Server user]$ nl -b a go.sh
1 #!/bin/sh
2
3 echo "ID~"`grep title reg_prop.xml | cut -d\" -f2 | ./toline.sh`
4 for v in 0*[0-9A-F].REG; do
5 echo -n "$v~"
6
7 while true; do
8 read line
9
10 if [ "$?" == "1" ]; then
11 break
12 fi
13
14 echo -n $line"~"
15 done <<EOF
16 `cut -d: -f2 $v`
17 EOF
18
19 echo
20 done
1. 第4行-20行的for循环是对650个文件依次进行处理。(对于分隔符,本来是想用分号,或者逗号,或者空格。结果这些字符在注册信息里全出现了,后来选了“~”号)。
2. 第7-15行是while循环,执行的基本功能是把每个信息文件拼成一行。
3. 16行是执行cut命令,提取文件中冒号右边的内容,把输出作为Here Documents送给while循环。
4. 在while循环中,第8行是使用read命令,每次读取一行,使用“~”拼成一行。注意这里有个特殊的处理:因为在信息文件中某一项注册项可能是空的,这样16行的输出可能中间有空行。因此,判断read的结束不能使用if [ "$line" == ""] 的方法。经过调查,发现可以从read的返回值获取是否到达行末的状态。如果是遇到Ctrl-D结束,那么返回值是1。如果是正常的回车键结束,即使没有任何内容,返回值也是0。因此,正确的判断是 if [ "$?" == "1" ];
5. 17行的EOF是代表Here Documents的结束。注意此处不能像写C程序一样,为了美观而把EOF向右缩进,因为SHELL规定EOF必须是该行唯一出现的内容,连空格都不能有。因此,这个EOF就暂时突出在这一行了。(通过将输入操作符改为“<<-”可以解决这个问题,但是这里也无伤大雅)。
6. 文件中的toline.sh是自已编写的另外一个常用脚本,用于把输入的若干文本行拼成一行,并且以“~”分隔。这个脚本的实现比较简单,建议留给读者自己练习编写。
五、总结
Shell脚本是进行服务器维护和日常管理的专用语言,是每一个Unix/Linux服务器管理员必须掌握的基本功。鉴于这种工具对文本文件处理的方便性,在应急处理一些工作时也是首选工具,本文中工作要求就是一个典型的应用。在Shell脚本的众多语法结构中,Here Documents可以说是比较深入的内容了,因此在网上的资料中并不算十分常见,即使是在Red Hat内置的大量脚本中,这种技术也不是用的特别普遍。但是深入掌握一种语法结构必将大大提高工作效率。在本文的形成过程中参考了网上其它一些文档和资料,读者可以参考更多的关于Shell脚本深入编程的文章,掌握这一利器,为我所用。
