Tcllib中的struct::list
包有计算最长公共子序列的工具,这是工具的关键部分。要使用,您将数据加载到 Tcl 中并将其拆分为行列表:diff
proc getLines {filename} {
set f [open $filename]
set result [split [read $f] "\n"]
close $f
return $result
}
然后你可以得到关于公共元素的信息(==公共行):
set sharedLineInfo [struct::list longestCommonSubsequence $file1_lines $file2_lines]
这将返回一对列表,其中每个列表是公共行的索引(从零开始计数);第一个列表用于第一个文件,第二个列表用于第二个文件。任何未列出的行号都将是已更改的行号。
还有一个功能可以反转提供的信息以获取有关如何将一个序列更改为另一个序列的说明:
set changes [struct::list lcsInvert $sharedLineInfo \
[llength $file1_lines] [llength $file2_lines]]
这将返回一个三元组列表,其中第一个是执行的操作(added
或changed
)deleted
,第二个和第三个是每个相关列表中的索引范围(即从零开始的行号)。
我不太确定如何获取这些信息并产生您正在寻找的东西,但我想我们可以像这样把它放在一起:
package require struct::list
proc getLines {filename} {
set f [open $filename]
set result [split [read $f] "\n"]
close $f
return $result
}
proc variedLines {filename1 filename2} {
set l1 [getLines $filename1]
set l2 [getLines $filename2]
lassign [struct::list longestCommonSubsequence $l1 $l2] common1
set result {}
for {set i 0} {$i < [llength $l1]} {incr i} {
if {$i ni $common1} {
lappend result [expr {$i + 1}]
}
}
return $result
}
如果您希望将结果写入文件,puts $f [join $someList "\n"]
可能会出现功能,但我将把它留作练习......</p>