阅读包装线

时间:2013-03-23 01:14:39

标签: tcl

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

喜欢:

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

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

我查看了'read'命令的文档,但似乎没有这样做。

非常感谢您的帮助。

谢谢, 格特

4 个答案:

答案 0 :(得分:2)

我不是那么有经验的Tcl程序员,所以我的命题很直接。

从你的问题我想,你逐行读取文件(我猜是使用“获取”)然后用线做(模式匹配)。所以,最直接的转发实现将是这样的(顺便说一下,其中一个问题是你喜欢用“前一行”的尾随空格和“下一行”的前导空格):

;# 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

答案 1 :(得分: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
}

答案 2 :(得分:0)

你可以很简单地看到Tcl如何处理这些参数:

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 ]

结果

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

如果你想把所有这些都作为单个字符串,那么"一些cmd"非常简单

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

输出

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

答案 3 :(得分:0)

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

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

这与Tcl相同的\换行替换。