我有两个文件。
0 10 20 30
10 20 30 40
0 10 23 34
文件a的值为(x1 y1 x2 y2格式)
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
答案 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_file
,for_file
和lassign
来自Tclx
包,这简化了生活。 lassign
成为从Tcl版本8.5开始的内置命令。read_file
包,就可以使用Tclx
。如果您有Tcl 8.4,8.5或更高版本,则无关紧要。Tclx
并且他/她正在运行Tcl 8.4,因此我必须使用lassign
技巧替换foreach
。