我有一个包裹行的文件。它恰好是包装多行的TCL代码。 (但它可能是任何作为换行规则的东西。)
喜欢:
set long [ some cmd { some long stuff \
more stuff \
even more stuff \
end of cmd} but going on \
end of set ]
我想将其解析为一行,以便我可以对其进行一些模式匹配。
我查看了'read'命令的文档,但似乎没有这样做。
非常感谢您的帮助。
谢谢, 格特
答案 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相同的\换行替换。