0

2 つのテキストを比較し、異なる行の行番号のみを返す tcl スクリプトの書き方を教えてもらえますか? 私はbashでそれを行う方法を知っていますが、tclにbashを含めることはあまりきちんとしていないようです.bashコマンドは次のとおりです:

    diff --old-line-format '%L' --new-line-format '' --unchanged-line-format ''  <(nl File1) <(nl File2) | awk '{print $1 }' > difflines

これを tcl に含めるために、次のことを行いました。

exec cat nl File1 > File11
exec cat nl File2 > File22
exec diff --old-line-format {%L} --new-line-format {} --unchanged-line-format {}  < 
File11 < File22 | awk {{print $1 }} > difflines

よりクリーンな方法はありますか?

また、違いがある場合、「子の異常終了」が表示されますが、これを回避するにはどうすればよいですか?

ありがとう

4

2 に答える 2

2

「子プロセスが異常終了しました」について、execマニュアルページから(強調鉱山):

パイプライン内のコマンドのいずれかが異常終了するか、強制終了または一時停止された場合、exec はエラーを返し、エラー メッセージにはパイプラインの出力が含まれ、その後に異常終了を説明するエラー メッセージが続きます。-errorcode 戻りオプションには、最後に発生した異常終了に関する追加情報が含まれます。コマンドのいずれかが標準エラーファイルに書き込み、その標準エラーがリダイレクトされず、-ignorestderr が指定されていない場合、exec はエラーを返します。エラー メッセージには、パイプラインの標準出力が含まれ、その後に異常終了 (存在する場合) に関するメッセージが続き、その後に標準エラー出力が続きます。

「コマンドが異常終了する」とは、コマンドがゼロ以外のステータスで終了することを意味します。grep や diff などの一部の一般的なコマンドは、正常であることを示すためにゼロ以外の終了ステータスを返すため、その exec 呼び出しをcatch

set rc [catch {exec bash -c {
    diff --old-line-format '%L' --new-line-format '' --unchanged-line-format ''  <(nl File1) <(nl File2) | awk '{print $1}' > difflines
}} output]

if {$rc == 0} {
    puts "no differences found"
} elseif {$rc == 1} {
    puts "differences found:"
    puts $output
} else {
    puts "diff returned an error: $output"
}
于 2013-01-19T15:44:52.990 に答える
2

Tcllibstruct::listパッケージには、ツールの重要な部分である最長共通部分列を計算するためのツールがあります。使用するには、データを Tcl にロードし、それを行のリストに分割します。diff

proc getLines {filename} {
    set f [open $filename]
    set result [split [read $f] "\n"]
    close $f
    return $result
}

次に、共通要素 (== 共通行) に関する情報を取得できます。

set sharedLineInfo [struct::list longestCommonSubsequence $file1_lines $file2_lines]

これは、リストのペアを返します。各リストは、共通行のインデックス (ゼロから数えます) です。最初のリストは最初のファイル用で、2 番目のリストは 2 番目のファイル用です。リストされていない行番号は、変更された行番号になります。

あるシーケンスを別のシーケンスに変更する方法についての指示を取得するために提供される情報を反転する機能もあります。

set changes [struct::list lcsInvert $sharedLineInfo \
        [llength $file1_lines] [llength $file2_lines]]

これはトリプルのリストを返します。最初は実行された操作 ( addedchangedまたはdeleted) で、2 番目と 3 番目は関連する各リストのインデックスの範囲 (つまり、0 から始まる行番号) です。

この情報をどのように取得して、探しているものを生成するかはよくわかりませんが、次のようにまとめることができると思います。

package require struct::list
proc getLines {filename} {
    set f [open $filename]
    set result [split [read $f] "\n"]
    close $f
    return $result
}
proc variedLines {filename1 filename2} {
    set l1 [getLines $filename1]
    set l2 [getLines $filename2]
    lassign [struct::list longestCommonSubsequence $l1 $l2] common1
    set result {}
    for {set i 0} {$i < [llength $l1]} {incr i} {
        if {$i ni $common1} {
            lappend result [expr {$i + 1}]
        }
    }
    return $result
}

結果をファイルに書き込みたい場合は、puts $f [join $someList "\n"]機能する可能性が高いですが、それは演習として残しておきます…</p>

于 2013-01-19T13:12:35.727 に答える