TCL比较文件中的两个字段并打印该行

时间:2013-02-21 11:33:00

标签: tcl

我有两个文件。

  • 提交
  

0 10 20 30

     

10 20 30 40

     

0 10 23 34

文件a的值为(x1 y1 x2 y2格式)

  • 文件b
  • 格式为P M M x y - (某个数字)
  

P M M 10 20 -100

     

P M M 20 30 -150

     

P M M 50 60 -100

在文件B中,我想搜索字段4,5(从P作为字段1开始)是否在文件a中的范围内。如果是,则不打印FileB的行,否则打印该行。

我们不打印文件b的行

  

x1< x< x2& y1< y< Y2

所以脚本的O / P应该是

文件c

  

P M M 50 60 -100


我在tcl中编写了以下脚本,但我的问题是没有在File a 中搜索文件b的所有内容。


set abc "b"
set ab "a"

set cord [open $ab "r"]

if [catch {open $abc r} FILE_R {
    puts "failed to read $abc"
    return -1
}

while { [gets $FILE_R line] >= 0 } {
    if [regexp {^#} $line ] {
    } else {
        set x_cord [lindex $line 3] 
        set y_cord [lindex $line 4]
        while { [gets $cord line] >= 0 } {
            set x1_cord [lindex $line 0]
            set y1_cord [lindex $line 1]
            set x2_cord [lindex $line 2]
            set y2_cord [lindex $line 3]

            if { [expr x1_cord < x_cord && x_cord < x2_cord && y1_cord < y_cord && y_cord < y2_cord ] == 1 } {
            } else {
                puts $line
            }
        }
    }
}

close $FILE_R

3 个答案:

答案 0 :(得分:1)

这一行:

if { [expr x1_cord < x_cord && x_cord < x2_cord && y1_cord < y_cord && y_cord < y2_cord ] == 1 } {
如果尊重,

在一个数字中是错误的。特别是,这些变量没有被读取。您还可以通过将expr置于if条件中来完成额外的工作,因为它们已经使用了相同的语法。相反,使用这个:

if {$x1_cord < $x_cord && $x_cord < $x2_cord && $y1_cord < $y_cord && $y_cord < $y2_cord} {

您似乎也在使用if {somecondition} {} else { somescript };这不是特别低效,但看起来很奇怪。只是否定条件并按照这样做:if {!(somecondition)} { somescript }

答案 1 :(得分:0)

首先打开坐标文件并读取每一行,直到你有x1,y1,x2,y2的每一个的最大值和最小值。这将是8个值。

然后打开第二个文件并读取每一行。然后将其拆分并与您的限制进行比较。

上面的问题是你打开每个文件一次但是每次有FILE_R行时你都试图重新读取coord文件。但是你永远不会回到文件的开头。如果你这样做,那将是非常低效但可能有效。首先获取限制然后处理第二个文件。

将线条与正则表达式匹配也更聪明,但是将它们与扫描分开。通过这种方式,您不太可能遇到Tcl认为重要的问题,例如开括号或分号或过多的空格。例如:

% scan "P M M 10 20 -100" {P M M %d %d %d} x y z
3
% list $x $y $z
10 20 -100

注意我们可以检查我们获得了正确数量的扫描参数(3)。

答案 2 :(得分:0)

这是我的解决方案:

package require Tclx

# Read file a.txt, which contains x1 y1 x2 y2
# After reading, coords will be
#     {{0 10 20 30} {10 20 30 40} {0 10 23 34}}
# which is a list of lists
set coords [split [read_file a.txt] \n]

# Read file b.txt, line by line
# where each line contains P M M x y -(some number)
for_file line b.txt {
    if {[regexp {^#} $line]} { continue }; # skip comment

    #lassign    $line p m1 m2 x y n; # parse the line into proper fields
    foreach {p m1 m2 x y n} $line {}; 
    set inrange 0; # assume out of range, will flag it if found otherwise
    foreach coord $coords {
        #lassign $coord x1 y1 x2 y2; # parse the range
            foreach {x1 y1 x2 y2} $coord {}
        if {$x1 < $x && $x < $x2 && $y1 < $y && $y < $y2} {
            set inrange 1; # we are in range, set the flag for not printing
        }
    }

    # Print if not in any range
    if {!$inrange} { puts $line }
}

讨论

  • 命令read_filefor_filelassign来自Tclx包,这简化了生活。 lassign成为从Tcl版本8.5开始的内置命令。
  • 要回答评论:只要您使用read_file包,就可以使用Tclx。如果您有Tcl 8.4,8.5或更高版本,则无关紧要。
  • 其余的代码是直截了当的,我希望你没有理解。
  • 由于user2095095无法访问Tclx并且他/她正在运行Tcl 8.4,因此我必须使用lassign技巧替换foreach