Home > Software design >  Hello, I need some help to copy the content of one file to another except from some corrupted lines
Hello, I need some help to copy the content of one file to another except from some corrupted lines

Time:04-09

I have a file with some thousands lines with the below format:

1.3.111.2.802.1.1.3.1.6.3.1.2.5.1.2  2  5
1.3.111.2.802.1.1.3.1.6.3.1.2.5.1.2  2  1
1.3.111.2.802.1.1.3.1.7.1.1.45.1.1.463040864     2  5
1.3.111.2.802.1.1.3.1.7.1.1.45.5.1.2     2  5
1.3.111.2.802.1.1.3.1.7.1.1.2.1.1.463040864  2  128
1.3.111.2.802.1.1.3.1.7.1.1.2.5.1.2  2  1
1.3.111.2.802.1.1.3.1.7.1.1.4.1.1.463040864 66  52428
1.3.111.2.802.1.1.3.1.7.1.1.4.5.1.2 66  3001
1.3.111.2.802.1.1.3.1.7.1.1.7.1.1.463040864  2  -858993460
1.3.111.2.802.1.1.3.1.7.1.1.7.5.1.2  2  1
1.3.111.2.802.1.1.3.1.7.1.1.8.1.1.463040864 66  204
1.3.111.2.802.1.1.3.1.7.1.1.8.5.1.2 66  5
1.3.111.2.802.1.1.3.1.7.1.1.45.1.1.463040864     2  1
1.3.111.2.802.1.1.3.1.7.1.1.45.5.1.2     2  1
1.3.6.1.4.1.2076.74.7.1.0    2  2
CKSUM:123376667

I want to copy all the lines from the current file in an other file, except of those that the last number after the "." is smaller than 0 and higher than 8191. For example I don't want the line 1.3.111.2.802.1.1.3.1.7.1.1.7.1.1.463040864 2 -858993460 to be included in the new file and also the last line not to be copied.


I have write this proc

proc isstest { inputfile tempfile } {

# open the target file for reading

set in [open $inputfile r]

# open a temp file

set out [open $tempfile w ]

while { [gets $in line] != -1 } {

      set varList_temp [split $line " "]

      set varList_temp1 [lindex $varList_temp 0]

      set varList [split $varList_temp1 "."]

      set ifdx 0

      foreach number $varList {

        set ifdx $number
        }
        
      if { $ifdx >= 1 || $ifdx <= 8191 } {  

        puts $out $line

But I have stacked how to discard the last line checksum if there're corrupted lines

the disered output should be like this:

1.3.111.2.802.1.1.3.1.6.3.1.2.5.1.2  2  5
1.3.111.2.802.1.1.3.1.6.3.1.2.5.1.2  2  1
1.3.111.2.802.1.1.3.1.7.1.1.45.5.1.2     2  5
1.3.111.2.802.1.1.3.1.7.1.1.2.5.1.2  2  1
1.3.111.2.802.1.1.3.1.7.1.1.4.5.1.2 66  3001
1.3.111.2.802.1.1.3.1.7.1.1.7.5.1.2  2  1
1.3.111.2.802.1.1.3.1.7.1.1.8.5.1.2 66  5
1.3.111.2.802.1.1.3.1.7.1.1.45.5.1.2     2  1
1.3.6.1.4.1.2076.74.7.1.0    2  2

CodePudding user response:

This uses a regular expression to capture the digits following the last dot, instead of splits and lindexs

set in [open $inputfile r]
set out [open $output w]

while {[gets $in line] != -1} {
    if {[string match {CKSUM*} $line]} then continue

    # capture the digits following the last dot
    if {[regexp {.*\.(\d )} $line -> key]  &&  0 <= $key && $key <= 8919} {
        puts $out $line
    }
}

close $in
close $out

CodePudding user response:

Well, in this case we can try treating each line as a list; the lines seem to be well-formed enough for that (is that first field an OID?)

while {[gets $inChannel line] >= 0} {
    if {[llength $line] <= 1 || [tcl::mathop::<= 0 [lindex $line end] 8191]} {
        puts $outChannel $line
    }
}

The tricky bit here is the use of tcl::mathop::<=, which is the command form of the <= expression operator, which allows us to check whether the value (from the last word of the line) is in the range 0 to 8191 without needing to repeat ourselves.


A more cautious approach would be this:

while {[gets $inChannel line] >= 0} {
    if {[catch {llength $line} length] || $length <= 1} {
        # Ill-formed and short lines get copied
        puts $outChannel $line
        continue
    }

    set value [lindex $line end]
    if {![string is integer -strict $value]} {
        # Lines with non-integers get copied
        puts $outChannel $line
        continue
    }
 
    if {[tcl::mathop::<= 0 $value 8191]} {
        # Lines with values in range get copied
        puts $outChannel $line
    }
}

It's possible to not repeat the puts but the resulting code is less clear in my opinion.

  • Related