TCL:打开文件,提取数据,复制文件并在之后进行操作

时间:2013-04-06 09:09:43

标签: file-io scripting tcl text-files

我想打开一个几乎包含以下内容的文本文件:

    $  
    *include_path
    path
    $
    $
    *include
    test.txt
    $
    $
    *include
    test1.txt
    $
    *include
    test1.txt
    $
    *INCLUDE
    test1.txt
    $

脚本应该能够搜索位于模式“include_path”下面的路径,将其保存到变量并将位于模式“include”下面的所有文本文件复制到特定文件夹。

大写的“INCLUDE”表示文本文件与主文本文件放在同一目录中。小写的“include”表示文本文件可以在“include_path”下面的路径中找到。

将所有文本文件复制到新文件夹后,应打开主文本文件,并删除或注释掉“include_path”行以及以下路径。

1 个答案:

答案 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列表中累积了这些文件(然后在最后打了一些琐碎的代码来打印出来)。

就个人而言,我更喜欢让我的配置文件 Tcl脚本。然后我可以使用source来解析它们。 (代码是数据,数据是代码,Tcl有工具可以安全地完成。)这不适用于你所描述的格式。