0

私は2つのファイルを持っています。

  • ファイル

0 10 20 30

10 20 30 40

0 10 23 34

ファイル a の値は (x1 y1 x2 y2 形式)

  • ファイル b
  • 形式は PMM xy -(数値)

PMM 10 20 -100

PMM 20 30 -150

PMM 50 60 -100

ファイルBで、フィールド4,5(フィールド1としてPから始まる)がファイルaの範囲内にあるかどうかを検索したい. そうであれば、FileB の行を印刷しないでください。そうでない場合は、その行を印刷します。

ファイル b の行を出力しません。

x1 < x < x2 & y1 < y < y2

そのため、スクリプトの O/P は

ファイル c

PMM 50 60 -100


私は tcl で次のスクリプトを作成しましたが、私の問題は、ファイル a 内のファイル b のすべてのコンテンツを検索していないことです。


set abc "b"
set ab "a"

set cord [open $ab "r"]

if [catch {open $abc r} FILE_R {
    puts "failed to read $abc"
    return -1
}

while { [gets $FILE_R line] >= 0 } {
    if [regexp {^#} $line ] {
    } else {
        set x_cord [lindex $line 3] 
        set y_cord [lindex $line 4]
        while { [gets $cord line] >= 0 } {
            set x1_cord [lindex $line 0]
            set y1_cord [lindex $line 1]
            set x2_cord [lindex $line 2]
            set y2_cord [lindex $line 3]

            if { [expr x1_cord < x_cord && x_cord < x2_cord && y1_cord < y_cord && y_cord < y2_cord ] == 1 } {
            } else {
                puts $line
            }
        }
    }
}

close $FILE_R
4

3 に答える 3

1

この行:

if { [expr x1_cord < x_cord && x_cord < x2_cord && y1_cord < y_cord && y_cord < y2_cord ] == 1 } {

という点ではかなり間違っています。特に、これらの変数は読み取られていません。また、同じ構文が既に使用されているためexpr、条件の中に入れることで余分な作業を行っています。if代わりに、これを使用します。

if {$x1_cord < $x_cord && $x_cord < $x2_cord && $y1_cord < $y_cord && $y_cord < $y2_cord} {

あなたも使用しているようですif {somecondition} {} else { somescript }; それは特に非効率的ではありませんが、奇妙に見えます。条件を否定して、次のようにします。if {!(somecondition)} { somescript }

于 2013-02-21T15:54:06.620 に答える
0

これが私の解決策です:

package require Tclx

# Read file a.txt, which contains x1 y1 x2 y2
# After reading, coords will be
#     {{0 10 20 30} {10 20 30 40} {0 10 23 34}}
# which is a list of lists
set coords [split [read_file a.txt] \n]

# Read file b.txt, line by line
# where each line contains P M M x y -(some number)
for_file line b.txt {
    if {[regexp {^#} $line]} { continue }; # skip comment

    #lassign    $line p m1 m2 x y n; # parse the line into proper fields
    foreach {p m1 m2 x y n} $line {}; 
    set inrange 0; # assume out of range, will flag it if found otherwise
    foreach coord $coords {
        #lassign $coord x1 y1 x2 y2; # parse the range
            foreach {x1 y1 x2 y2} $coord {}
        if {$x1 < $x && $x < $x2 && $y1 < $y && $y < $y2} {
            set inrange 1; # we are in range, set the flag for not printing
        }
    }

    # Print if not in any range
    if {!$inrange} { puts $line }
}

討論

  • コマンド、、、read_fileおよびfor_filelassignパッケージからのTclxものであり、これにより作業が大幅に簡素化されます。はlassign、Tclバージョン8.5以降の組み込みコマンドになります。
  • コメントに答えるには:パッケージread_fileを使用する限り使用できます。TclxTcl 8.4、8.5、またはそれ以降を使用しているかどうかは関係ありません。
  • 残りのコードは単純明快です。問題なく理解できることを願っています。
  • user2095095にはアクセス権がなくTclx、Tcl 8.4を実行しているため、このトリックに置き換える必要がlassignありforeachます。
于 2013-02-22T05:23:34.320 に答える
0

最初に座標のファイルを開き、x1、y1、x2、y2のそれぞれの最大値と最小値が得られるまで各行を読み取ります。これは8つの値になります。

次に、2番目のファイルを開き、各行を1回読み取ります。次に、それを分割して、制限と比較します。

上記の問題は、各ファイルを1回開いても、FILE_R行があるたびにcoordファイルを再読み取りしようとしていることです。ただし、ファイルの先頭に戻ることはありません。そうした場合、それは非常に非効率的ですが、機能する可能性があります。最初に制限を取得してから、2番目のファイルを処理します。

また、行を正規表現と一致させ、スキャンで分割する方が賢明です。このようにして、Tclが重要と見なすもの、たとえば中括弧やセミコロン、またはスペースの数が多すぎるという問題に遭遇する可能性が低くなります。例えば:

% scan "P M M 10 20 -100" {P M M %d %d %d} x y z
3
% list $x $y $z
10 20 -100

スキャンされたパラメーターの数が正しいことを確認できることに注意してください(3)。

于 2013-02-21T12:34:58.453 に答える