Version 4 of scanfile

Updated 2002-07-16 16:44:08

scanfile is one of a set of commands designed to assist the user in looking through an open file for matches against a regular expression.

scanfile actually is the 'loop' that causes the evaluations to take place.

scanfile ?-copyfile copyFileId? contexthandle fileId

Scan the file specified by fileId, starting from the current file position. Check all patterns in the scan context specified by contexthandle against it, executing the match commands corresponding to patterns matched.

If the optional -copyfile argument is specified, the next argument is a file ID (see open) to which all lines not matched by any pattern (excluding the default pattern) are to be written. If the copy file is specified with this flag, instead of using the scancontext copyfile command, the file is disassociated from the scan context at the end of the scan.

This command does not work on files containing binary data (bytes of zero).


Hopefully someone will add in some examples here. In particular, an example that demonstrates how to change file lines based on regular expression hits would be appreciated.


LV wrote this attempt, but the example demonstrates that two matches on the same line results in the line being output twice!

 #! /usr/tcl84/bin/tclsh
 # Author: [Larry W. Virden]
 # Date: July 16, 2002

 package require Tclx

 # Set up the input data
 set fout [open "/tmp/testdata.txt" "w"]
 puts $fout "test line 1"
 puts $fout "test line 2 xyz"
 puts $fout "test line 3 abc"
 puts $fout "test line 4 ABC"
 puts $fout "test line 5 aBc"
 puts $fout "test line 6 ABc"
 puts $fout "test line 7 AbC"
 puts $fout "test line 8"
 puts $fout ""
 close $fout

 global matchInfo
 set replace_cnt 0

 proc replace {string index newvalue} {
        global matchInfo fout replace_cnt
        puts $fout [string replace $string [lindex $index 0] [lindex $index 1] $newvalue]
        incr replace_cnt
        return
 }

 set con1 [scancontext create]

 # Prime the context for the same file scan
 scanmatch -nocase $con1 {(abc)}  {replace $matchInfo(line) $matchInfo(subindex0) "AbC"}
 scanmatch $con1 {(xyz)}  {replace $matchInfo(line) $matchInfo(subindex0) "XYZ"}
 scanmatch $con1 {(test line 8)}  {replace $matchInfo(line) $matchInfo(subindex0) "123"}
 scanmatch $con1 {(test line 2)}  {replace $matchInfo(line) $matchInfo(subindex0) "test line 2b"}

 # Okay, use the context on the file.
 set fin [open "/tmp/testdata.txt" "r"]
 set fout [open "/tmp/new.testdata.txt" "w"]
 scanfile -copyfile $fout $con1 $fin
 close $fin
 close $fout
 puts [format "This run performed %d replacements." $replace_cnt]

See also scancontext and scanmatch.


Category Command, a part of TclX