Tcl 如何标记文件中的行?

Tcl 如何标记文件中的行?,tcl,Tcl,我有一个文件test1: Par1 Par2 Par3 Par4 Par1 Par5 Par5 我制作了这个Tcl来过滤它: set thefile [open test1 "r"] set is_Par1 0 set is_Par3 0 while {![eof $thefile]} { set line [gets $thefile] if { [regexp {Par1} $line] } { set thefile2

我有一个文件test1:

Par1  
Par2  
Par3  
Par4  
Par1  
Par5  
Par5  
我制作了这个Tcl来过滤它:

set thefile [open test1 "r"]
set is_Par1 0
set is_Par3 0
while {![eof $thefile]} {
    set line [gets $thefile]
    if { [regexp {Par1} $line] } {
            set thefile2 [open test2 "w"]
            set is_Par1 1
    }
    if { [regexp {Par3} $line] } {
            set is_Par3 1
            set is_Par1 0
    }
    if { $is_Par1 && !$is_Par3 } {
            puts $thefile2 $line
    }
    if { [regexp {Par4} $line] } {
            set is_Par3 0
            close $thefile2
    }
}
close $thefile
让我们假设文件和模式更复杂(我简化了它)

我有一个结果:

Par1
Par5
Par5
Par1
Par2
但我想得到这个结果:

Par1
Par5
Par5
Par1
Par2

我看不出是我的错

在输入中遇到第一个
Par1
时打开输出文件,然后在读取第一个
Par4
时关闭它。到目前为止,一切顺利。但是,当您到达第二个
Par1
时,您只需继续读取并重新打开输出文件。这会覆盖输出文件


因此,我猜您希望在找到第一个
Par4
后停止读取输入,对吗?

当您在输入中遇到第一个
Par1
时打开输出文件,然后在读取第一个
Par4
时关闭它。到目前为止,一切顺利。但是,当您到达第二个
Par1
时,您只需继续读取并重新打开输出文件。这会覆盖输出文件


因此,我猜您希望在找到第一个
Par4
后停止读取输入,对吗?

问题是,您的代码在第一次看到
Par1
时打开了
test2
文件,编写了一些行,在看到
Par4
时关闭它,然后在下次看到
Par1
时再次打开它,该模式使它在添加更多行之前将文件截断为零。(当然,当脚本终止时,文件会自动关闭。)

当您找到第一个
Par4
时,停止处理
test1
中的行(通过
break
ing外部循环),或者以追加模式打开,以便至少第一批感兴趣的行不会丢失:

set thefile2 [open test2 "a"]

问题是,您的代码在第一次看到
Par1
时打开
test2
文件,写入一些行,在看到
Par4
时将其关闭,然后在下次看到
Par1
时再次打开该文件,该模式使其在添加更多行之前将文件截断为零。(当然,当脚本终止时,文件会自动关闭。)

当您找到第一个
Par4
时,停止处理
test1
中的行(通过
break
ing外部循环),或者以追加模式打开,以便至少第一批感兴趣的行不会丢失:

set thefile2 [open test2 "a"]

您不想用
eof
控制while循环:

假设要从第一个Par1行开始打印,在Par4处停止打印,并排除所有Par3行:

set f_in [open test1 r]
set f_out [open test2 w]
set started false
while {[gets $f_in line] != -1} {
    if {[string first Par1 $line] != -1} {set started true}
    if {!$started} continue
    if {[string first Par3 $line] != -1} continue
    if {[string first Par4 $line] != -1} break
    puts $f_out $line
}
close $f_in
close $f_out

您不想用
eof
控制while循环:

假设要从第一个Par1行开始打印,在Par4处停止打印,并排除所有Par3行:

set f_in [open test1 r]
set f_out [open test2 w]
set started false
while {[gets $f_in line] != -1} {
    if {[string first Par1 $line] != -1} {set started true}
    if {!$started} continue
    if {[string first Par3 $line] != -1} continue
    if {[string first Par4 $line] != -1} break
    puts $f_out $line
}
close $f_in
close $f_out

我不想追加,我只想要第一部分,也许我应该在while之外打开我的文件?@heyhey:在while之外打开文件肯定会减少混乱,一旦找到所有需要的东西,你应该
从循环中中断
。在你完成了所有有用的工作之后继续这样做是浪费。我不想附加,我只想要第一部分,也许我应该在while之外打开我的文件?@heyhey:在while之外打开文件肯定会减少混乱,一旦你找到了所有你想要的东西,你应该
从循环中中断
。在你完成了所有有用的工作之后继续干下去是浪费。