2

行が折り返されたファイルがあります。たまたま複数行をラップする TCL コードです。(ただし、行折り返しのルールとしては何でもかまいません。)

お気に入り :

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

これを 1 行に解析して、パターン マッチングを実行できるようにします。

「読み取り」コマンドのドキュメントを見ましたが、そうではないようです。

あなたの助けに感謝します。

ありがとう、ゲルト

4

4 に答える 4

2

私は経験豊富な Tcl プログラマーではないので、私の提案は非常に単純です。

あなたの質問から、ファイルを1行ずつ読んで(「gets」を使用していると思います)、その行で何かを行う(パターンマッチング)と思います。したがって、最も単純な実装は次のようになります (ちなみに、質問の 1 つは、「前の」行の末尾の空白と「次の」行の先頭の空白をどうするかということです):

;# 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 に答える