文章出处:51testing 作者:叶晖 兰海 发布时间:2006-03-17

摘 要:unix下使用TCL脚本读取配置文件;错误处理.

关键词:TCL、配置文件、unix

一.应用范围
在实际工作中,TCL脚本对于一些简单的工作裨益甚大。通常编写脚本都有一定的模式,首先从配置文件读入配置项,初始化变量,然后进行处理,最后输出,在程序的运行过程中需要把一些信息写入日志文件,而调试信息写入日志文件和直接输出到屏幕都可以。

使用任何一种脚本,通常也都会根据实际情况建立起自己的函数库,而这个函数库中对配置文件配置项的读取无疑是非常基本而重要的。

这篇文章的本意是引导刚接触TCL脚本的朋友尽快上手,所以有些细节的说明文字比较细。

二.程序讲解
构建一个配置文件,尽可能的接近实际应用:

文件名:config.ini

文件内容:

#

# 这是注释行

#

[]

key1=value1 # 注释

[section1]

key2=value2

[section2]

key1=value2

[section1]

key1=xxxxxx # 这是最后的返回

[section1]

key1=value2

现在开始对程序的说明:

;#-------------------------------------------------------------------------

;# 功能:从配置文件中读取配置项

;# 输入:1. configFile :配置文件名称

;# 2. Section : 段名称

;# 3. Key : 关键字

;# 4. Comment : 注释符,缺省为井号

;# 5. Equal : 关键字和值的分隔符,缺省为等号

;# 输出:1. Value : 相应的值

;#-------------------------------------------------------------------------

1. 过程的定义:

格式:proc name args body

要点:

Ø 参数列表使用花括号引起;

Ø 变量没有类型;

Ø 变量之间使用空格间隔;

Ø 如果参数有缺省值,使用花括号引起,并赋值

proc getConfig { configFile Section Key {Comment "#"} {Equal "="}} {

set Value "" ;# 记录过程返回的值

set FindSection 0 ;# 记录是否找到了section

2.错误的处理

格式:catch script ?varName?

功能:执行script,如果成功返回TCL_OK(0),否则返回TCL_ERROR(1),提示结果存在varName中。比如下面如果打开文件成功,errMsg返回的就是类似file3这样的字符串,此时err返回的是TCL_OK,就是零;如果文件不存在,errMsg返回的类似:couldn't open "config1.ini": no such file or directory,此时err返回TCL_ERROR,就是一。

3.文件的读写

格式:openfile fileName ? access ? permission

讲解:

Ø fileName是文件名称;

Ø access是存取模式,可以为r, r+, w, w+, a, a+ 六种模式,r 、r+ 和a 三种模式文件必须已经存在,其他三种模式文件不存在就创建一个。本文用的 r 模式,所以文件不存在会提示错误,而不是自动建立一个;

Ø permission是权限,举例说明:
有权限为:000 000 000 :第一组三位为user权限;第二组三位为同组其他用户的权限;第三组三位为其他组所有人的权限。每个三位的权限依次代表读,写,执行。如果有相应的权限就设置为一,没有设置为0。然后三位为组转成十进制数。

Ø 文件打开后就可以使用其文件id,使用完后记得关闭文件

;# 打开配置文件

set err [catch {set fileid [open $configFile r]} errMsg]

if {$err == 1} {

puts "errMsg : $errMsg"

return $Value

}

;# 成功打开文件后, 一行一行的加以分析

set rowid 0 ;#记录当前行数,程序调试时打印调试信息使用的

seek $fileid 0 start ;# 定位到文件头

while {[eof $fileid] != 1} { ;# 读取文件内容

4.变量的自动增长使用命令 incr,也可以使用 set rowid [expr $rowid + 1],显然前者更简捷

incr rowid ;# 记录行数, 从一开始

;# 读出一行

gets $fileid line

5.先期处理行,因为注释有两种情况,行中的注释和整行注释,先去掉注释,然后去左右空格就可以得到真正需要的内容;如果先去空格,再去注释,由于行中的注释和内容之间有空格,这样最后得到的内容在去掉行中注释后,会在后面留下一些空格。所以需要先去掉注释,后去掉空格。

6.得到一个字符串在另一个字符串中首先出现的位置,使用函数string first

格式:string first string1 string2

讲解:返回string1在string2中第一次出现的位置;如果string1不在string2中,返回-1

7.下面有一个细节是初学者经常犯错的地方,那就是:} else { ,这里必须严格的 花括号,空格,else,空格,花括号,不能把花括号写到上一行或者下一行。

8.返回一个字符串的子串使用string range函数

格式:string range string1 frompos topos

讲解:取string1的从frompos到topos之间的字符串,注意这里字符串下标是从零开始的,所以用string length string1得到的字符串的长度比字符串最后一个字符的位置值要大一。如果取一个字符串中的某个字符就可以使用函数string index string1 pos。

9.expr 和unix shell中一样,是进行数学运算的函数。

;# 先去掉注释, 再去掉两端的空格

set commentpos [string first $Comment $line] ;# 得到注释符号的位置

if { $commentpos == 0 } {

;# 行以注释符号开头,忽略掉该行

} else {

if { $commentpos != -1 } { ;# 行中有注释符号,去掉注释

set line [string range $line 0 [expr $commentpos-1]]

}

set line [string trim $line] ;# 去掉两端的空格

;# puts "$rowid : line : $line"

10.在tcl脚本中,循环中有break命令跳出循环,continue跳到循环的开头。不过因为括号的使用,其实这里写不写continue都没有问题。

;# 如果是空就继续循环

if { $line == "" } {

;# 回循环

continue

} else {

;# 先找section

set linelen [string length $line] ;#字符串长度

set lastpos [expr $linelen - 1 ] ;#字符串最后的位置

;# puts "$rowid :len: $linelen lastpos: $lastpos"

if { [string index $line 0] == "\[" && [string index $line $lastpos] == "\]" } {

;# 如果是查找的section, 修改标志位;如果不是相应的section, 需要将标志重新赋值

if { [string range $line 1 [expr $lastpos - 1 ]] == $Section } {

;# puts "$rowid: find section : $Section"

set FindSection 1

} else {

set FindSection 0

}

} else {

;# 已经找到了section才继续找key

if { $FindSection == 1 } {

set equalpos [string first $Equal $line] ;# 得到等号的位置

if { $equalpos != -1} {

;# 如果就是找寻的key,结束循环

if { [string range $line 0 [expr $equalpos - 1]] == $Key } {

puts "$rowid: find key"

set Value [string range $line [expr $equalpos + 1] [string length $line]]

puts "$rowid: find value: $Value"

break

}

} else {

;# 回循环

}

} else {

;# 回循环

}

}

}

}

}

;# 关闭文件

close $fileid

return $Value

}

set val ""

;# 测试正常情况下

set val [getConfig "config.ini" "section1" "key1"]

puts "val : $val"

;# 测试文件不存在的情况下

set val [getConfig "config1.ini" "section1" "key1"]

puts "val : $val"

该程序在unix 环境下调试通过。

三.伪代码
为了便于理解程序,特写了下面的伪代码:

打开配置文件

IF 出错 THEN

过程结束

END IF

文件打开成功,定位到文件头

WHILE 没有到文件尾

读出一行

处理得到的行,先去掉行中的注释,再去掉行左右的空格

IF 行为空 THEN

ELSE

行不为空

IF [开头 ]结束 THEN

得到SECTION

IF 得到的SECTION就是要找的SECTION THEN

置标志位

ELSE

清空标志位

END IF

ELSE

IF 已经找到SECTION了 THEN

IF 行中有等号 THEN

IF 等号左边的是在查找的KEY THEN

取得等号右边的值,跳出循环

ELSE

等号左边不是在查找的KEY,继续下一行

END IF

ELSE

行中没有等号,继续下一行

END IF

ELSE

还没有找到SECTION,继续下一行

END IF

END IF

END IF

关闭文件

返回值

四.讨论
这个程序本身比较简单,主要目的是想通过这个程序让tcl初学者对tcl有个感性认识。真正在工作使用中,这个脚本需要改进的地方还有很多。

比如配置文件比较小的话,可以读一个配置项打开一次文件。当配置文件大了以后,这种方法显然效率比较低,可能需要一次将文件的内容全部读入一个列表中,然后进行读取,这样速度会有提高。再比如错误处理只是在过程中将错误信息显示到屏幕上,是不是应该定义一个错误信息的全局变量来传出过程,或者使用upvar 直接修改错误信息变量。否则返回的值是空,并不能确定是配置的值的确是空还是执行中出现了错误。

抛砖引玉,共勉。如有错误,望不吝赐教。

使用TCL脚本读取配置文件相关推荐

  1. 如何用shell脚本读取配置文件

    setup.ini内容示例: Install mysql + nginx + php + java=install_mysql install_php install_nginx install_ja ...

  2. shell脚本读取配置文件【有图有真相】

    配置文件config.properties #以下是配置文件内容,配置文件文件名为config.properties username=jack password=33281 shell脚本(脚本名为 ...

  3. python读取配置文件存在某配置_Python读取配置文件(config.ini)以及写入配置文件

    一.读取配置文件 我的目录如下,在config下有一个config.ini配置文件 配置文件内容# 定义config分组 [config] platformName=Android appPackag ...

  4. tcl把文本产生html,TCL脚本数据文件格式(译文)

    TCL脚本数据文件格式 简介 一个典型的tcl脚本把它的内部数据保存在列表和数组(tcl中两种主要的数据结构)中.比如,假定你想写一个能将数据先保存在磁盘上,然后再读取的tcl应用程序, 这将使你的用 ...

  5. TCL脚本语言基础介绍

    Tcl简介(一):Tcl 语法 Tcl 语法 Tcl是一种很通用的脚本语言,它几乎在所有的平台上都可以释运行,其强大的功能和简单精妙的语法会使你感到由衷的喜悦,这片文章对 Tcl有很好的描述和说明.如 ...

  6. python火狐配置文件_Python+Selenium中级篇之4-封装一个自己的类-浏览器引擎类/Python读取配置文件内容...

    封装一个自己的类-浏览器引擎类 前一篇文章我们知道了,如何去封装几个简单的Selenium方法到我们自定义的类,这次我们编写一个类,叫浏览器引擎类,通过更改一个字符串的值,利用if语句去判断和控制启动 ...

  7. MySQL读取配置文件的顺序、启动方式、启动原理

    一.MySQL读取配置文件的顺序 读取顺序:/etc/my.cnf > /etc/mysql/my.cnf > /usr/etc/my.cnf > ~/.my.cnf 命令验证: [ ...

  8. 读取 配置文件_自动化测试中,如何读取配置文件内容?

    构建测试知识体系,欢迎关注 " 自动化中的配置信息,比如域名.数据库信息.kafka信息等,通常是放到配置文件中的.那么如何读取配置文件中的信息呢?" 自动化测试代码中,像请求域名 ...

  9. python读取配置文件列表失败_从配置文件python中读取列表

    美好的一天, tldr;配置读取脚本返回单个字符而不是字符串. 我正在编写一个程序,可以使用SCPI命令连接到各种仪器.除此之外,每台仪器都必须进行不同的初始化,并且应该添加新的仪器,因此我制作了一个 ...

最新文章

  1. 今天大佬告诉你Spring Boot 实现通用 Auth 认证的 4 种方式!
  2. 秋色园QBlog技术原理解析:Web之页面处理-内容填充(八)
  3. 20172304 2017-2018-2 《程序设计与数据结构》第六周学习总结
  4. 网络空间安全导论期末复习资料
  5. 艾伦·图灵天才的一生,为什么却蒙羞而死?这是被时代所亏欠的一生!
  6. 正确的座机号码格式_电话号码的正确写法
  7. 我国资本市场程序化交易的风险控制策略
  8. 爬虫抓取暗黑3国服天梯榜数据及分析
  9. linux firefox flashplayer 升级,在deepin中更新火狐浏览器firefox和firefox-flashplayer的方法...
  10. 日日日日日日日日日日
  11. 立陶宛央行抢跑数字货币背后:前瞻的区块链战略 中国已有企业布局
  12. [ZZ]为什么选择傲游
  13. 网络打印机安装教程:HP LaserJet Pro MFP M226dw,Windows解决外网无法使用打印机问题
  14. 基于iReport5.5+JavaBean+Struts2(注解方式)的报表设计与查看
  15. 南工院计算机答辩,人工智能与计算机学院举行“智能之星”评选答辩会
  16. 基于JSP开发的电影票预订系统 JAVA MySQL
  17. Win7系统开机提示Flash Helper Service 已停止工作解决办法!
  18. 记录解决启动prometheus-kafka-adapter提示“client has run out of available brokers to talk to“的问题
  19. vba:消息框基础,msgbox
  20. Android官方API文档完整版(分享)

热门文章

  1. 查看suse linux版本
  2. Webview是什么?
  3. todesk远程控制软件的使用
  4. 2022年最新吉林水利水电施工安全员模拟试题题库及答案
  5. [刷题之旅no14]P1553 数字反转(升级版)
  6. 使用asw sdk 开发java
  7. 【解决】openwrt编译错误automake错误255
  8. 概率论与数理统计学习笔记——第7讲——连续型随机变量(2.5.5正态分布)
  9. 【反内卷】开创全新AI多模态任务一视听分割:附原理、代码实践、优化教程(一)
  10. 古典密码(部分合集)