如何使用tcl屏蔽文件中包含的敏感信息?

时间:2013-03-19 07:38:29

标签: tcl password-encryption

我正在尝试实现一个读取文本文件的tcl脚本,并屏蔽包含它的所有敏感信息(如密码,IP地址等)并将输出写入另一个文件。

截至目前,我只是用 * *或#####替换此数据,并使用regexp搜索整个文件,以找到我需要屏蔽的内容。但由于我的文本文件可能是100K行或更多行,因此效率极低。

我是否可以使用内置的tcl函数/命令来更快地完成此操作?任何附加软件包都提供额外的选项,可以帮助完成这项工作吗?

注意:我正在使用tcl 8.4(但如果有更新版本的tcl有办法,请指点我们)

3 个答案:

答案 0 :(得分:2)

一般来说,您应该将代码放在一个程序中,以便从Tcl中获得最佳性能。 (你在8.5和8.6中有一些更多的相关选项,比如lambda术语和类方法,但它们与程序密切相关。)你还应该注意其他一些事情:

  • 将表达式放在大括号(expr {$a + $b}而不是expr $a + $b)中,因为这样可以实现更有效的编译策略。
  • 仔细选择您的频道编码。 (如果您执行fconfigure $chan -translation binary,该频道将传输字节而非字符。但是,gets在面向字节的频道上效率不高在8.4中。使用-encoding iso8859-1 -translation lf将带来大部分好处。)
  • Tcl很好地进行了通道缓冲。
  • 可能值得使用不同版本的Tcl对您的代码进行基准测试,以确定哪种方法效果最佳。尝试使用tclkit build进行测试,如果您不想为安装多个Tcl解释器而进行测试(
  • )。

进行面向行的转换的惯用方法是:

proc transformFile {sourceFile targetFile RE replacement} {
    # Open for reading
    set fin [open $sourceFile]
    fconfigure $fin -encoding iso8859-1 -translation lf

    # Open for writing
    set fout [open $targetFile w]
    fconfigure $fout -encoding iso8859-1 -translation lf

    # Iterate over the lines, applying the replacement
    while {[gets $fin line] >= 0} {
        regsub -- $RE $line $replacement line
        puts $fout $line
    }

    # All done
    close $fin
    close $fout
}

如果文件足够小以至于它可以很容易地放入内存中,那么效率更高,因为整个匹配替换循环被提升到C级别:

proc transformFile {sourceFile targetFile RE replacement} {
    # Open for reading
    set fin [open $sourceFile]
    fconfigure $fin -encoding iso8859-1 -translation lf

    # Open for writing
    set fout [open $targetFile w]
    fconfigure $fout -encoding iso8859-1 -translation lf

    # Apply the replacement over all lines
    regsub -all -line -- $RE [read $fin] $replacement outputlines
    puts $fout $outputlines

    # All done
    close $fin
    close $fout
}

最后,正则表达式不一定是进行字符串匹配的最快方法(例如,string match要快得多,但接受更受限制的模式类型)。将一种替换代码转换为另一种代码并使其快速发展并非百分之百(REs非常灵活)。

答案 1 :(得分:1)

一个100K行的文件并不多(除非每行都是1K字符长:)所以我建议你read将整个文件放到var中并在那个var上进行替换:

set fd [open file r+]
set buf [read $fd]
set buf [regsub -all $(the-passwd-pattern) $buf ****]
# write it back
seek $fd 0; # This is not safe! See potrzebie's comment for details.
puts -nonewline $fd $buf
close $fd

答案 2 :(得分:1)

特别是对于非常大的文件 - 如上所述 - 它不是将整个文件读入变量的最佳方式。一旦系统内存不足,您就无法阻止应用程序崩溃。对于由换行符分隔的数据,最简单的解决方案是缓冲一行并处理它。

只是举个例子:

# Open old and new file
set old [open "input.txt" r]
set new [open "output.txt" w]
# Configure input channel to provide data separated by line breaks
fconfigure $old -buffering line
# Until the end of the file is reached:
while {[gets $old ln] != -1} {
    # Mask sensitive information on variable ln
    ...
    # Write back line to new file
    puts $new $ln
}
# Close channels
close $old
close $new

我想不出在Tcl中处理大文件的更好方法 - 请随时告诉我任何更好的解决方案。但是Tcl并不是为了处理大数据文件。对于实际性能,您可以使用编译而不是脚本编程语言。

修改:在while循环中替换![eof $old]