我想打开一个几乎包含以下内容的文本文件:
$ *include_path path $ $ *include test.txt $ $ *include test1.txt $ *include test1.txt $ *INCLUDE test1.txt $
脚本应该能够搜索位于模式“include_path”下面的路径,将其保存到变量并将位于模式“include”下面的所有文本文件复制到特定文件夹。
大写的“INCLUDE”表示文本文件与主文本文件放在同一目录中。小写的“include”表示文本文件可以在“include_path”下面的路径中找到。
将所有文本文件复制到新文件夹后,应打开主文本文件,并删除或注释掉“include_path”行以及以下路径。
答案 0 :(得分:1)
这是一种稍微棘手的解析格式,因为它包含了要忽略的行,需要同时对多行执行操作。这是我第一次解析它:
set f [open "the_file_to_parse.txt"]
while {[gets $f line] >= 0} {
switch -- [string trim $line] { # Don't know if the space is significant
"*include_path" {
set path [file normalize [string trim [gets $f]]]
}
"*include" {
lappend files [file join $path [string trim [gets $f]]]
}
"*INCLUDE" {
lappend files [file normalize [string trim [gets $f]]]
}
}
# No ‘default’ clause, so unrecognized lines are ignored
}
close $f
# Now, show what we've found out
foreach filename $files {
puts "Will include file at $filename"
}
这里的关键技巧:
while {[gets …] >= 0} …
是循环文件行的惯用方法。主要的替代方案 - 一次性将它们全部压缩,分割换行,并使用foreach
进行迭代 - 在这里不起作用,因为有时需要每次迭代读取多行。file normalize
,所以我们最终得到了绝对路径。但是,我假设这些文件基本上都与当前目录相关。如果不是这样(例如,如果文件应该相对于配置文件的位置),我们可以使用其他技术来使其正确。但是,在内部使用绝对路径名是一个非常好的主意:它可以避免各种混淆。 (并且不要在脚本中cd
;即使它在语义上有明确的定义,它也会使事情混淆不清。) 就个人而言,我更喜欢让我的配置文件是 Tcl脚本。然后我可以使用source
来解析它们。 (代码是数据,数据是代码,Tcl有工具可以安全地完成。)这不适用于你所描述的格式。