2

我有一个带有换行的文件。它恰好是包含多行的 TCL 代码。(但它可以是任何作为换行规则的东西。)

喜欢 :

set long [ some cmd { some long stuff \
  more stuff \
  even more stuff \
  end of cmd} but going on \
  end of set ]

我想将其解析为一行,以便可以对其进行一些模式匹配。

我查看了“读取”命令的文档,但似乎没有这样做。

非常感谢您的帮助。

谢谢,格特

4

4 回答 4

2

我不是那么有经验的 Tcl 程序员,所以我的提议非常直截了当。

从您的问题我猜,您逐行读取文件(我猜使用“gets”),然后对该行执行某些操作(模式匹配)。因此,最直接的实现将是这样的(顺便说一句,问题之一是您喜欢如何处理“前”行的尾随空格和“下”行的前导空格):

;# Note: The code bellow was not tested, and may not run cleanly,
;# but I hope it shows the idea.

;# Like "gets", but concatenates lines, which finish with "\" character with
;# the next one.
proc concatenatingGets {chan} {
    set wholeLine ""
    set finishedReadingCurentLine no

    while {! $finishedReadingCurrentLine } {

        set currentLine [gets $chan]

        ;# more complicated rule can be used here for concatenation
        ;# of lines

        if {[string index $currentLine end] == "\\"} {

            ;# Decide here what to do with leading and trailing spaces.
            ;# We just leave them as is (only remove trailing backslash).
            ;# Note, that Tcl interpreter behaves differently.

            append wholeLine " " [string range $currentLine 0 end-1]

        } else {

            set finishedReadingCurrentLine yes

        } ;# if-else strig is to be concatenated

    } ;# while ! finishedReadingcurrentLine

} ;# concatenatingGets

;# Now use our tweaked gets:
set f [open "myFileToParse.txt" r]
while {![eof $f]} {
    set currentLine [concatenatingGets $f]

    ;# ... Do pattern matching ot current line, and whatever else needed.

}
close $f
于 2013-03-23T19:53:26.237 回答
1

由于您正在阅读 Tcl 代码,因此您可以使用 Tcl 提供的工具来提供帮助。特别是,info complete将说明字符串是否包含“完整”命令,这对于检测续行和多行文字(例如过程体)非常有用。唯一的诀窍是,只有在您输入换行符时,一切才能正常工作。因此:

set buffer {}
set fd [open $thefilename]
# Next line is idiomatic "read by lines" pattern
while {[gets $fd line] >= 0} {
    append buffer \n $line
    # IMPORTANT: need extra newline at end for this to work with
    # backslash-newline sequences.
    if {![info complete $buffer\n]} {
        # Get next line
        continue
    }
    processACompleteCommand $buffer
    set buffer {}
}
close $fd
# Deal with the last command if necessary (EOF is always a command terminator)
if {$buffer ne ""} {
    processACompleteCommand $buffer
}
于 2013-03-23T23:29:33.510 回答
0

如果整个文件有足够的内存:

foreach line [split [regsub -- "\n\$" [regsub -all -- "\\\\\n\[\[:blank:\]\]*" [read stdin] " "] ""] "\n"] {
    # ...
}

这与 Tcl 所做的 \newline 替换相同。

于 2013-03-23T04:55:52.190 回答
0

You can see how Tcl handles the arguments very simply:

proc some {args} {
    foreach arg $args {
        puts $arg
    }
}
set long [ some cmd { some long stuff \
  more stuff \
  even more stuff \
  end of cmd} but going on \
  end of set ]

results in

cmd
 some long stuff  more stuff  even more stuff  end of cmd
but
going
on
end
of
set

If you want all this as a single string, then "some cmd" is pretty simple

proc some args {join $args}
set long [some cmd ...]
puts $long

outputs

cmd  some long stuff  more stuff  even more stuff  end of cmd but going on end of set
于 2013-03-23T04:06:32.147 回答