is the name of a common filesystem utility on many Unix or unix like systems.Folklore says that the name represents a command that developers in the old days used to issue within their editor or other similar program:g/re/pwhich was a global {regular expression} print command.Grep reads through one or more input streams (stdin or files), searching for a string of text which represents some for of a regular expression, and, depending on options provided, may produce the matching lines of input.
RS wrote this tiny, and feature-poor, emulation for use on PocketPC (but it should run elsewhere too):
proc grep {re args} {
set files [eval glob -types f $args]
foreach file $files {
set fp [open $file]
while {[gets $fp line] >= 0} {
if [regexp -- $re $line] {
if {[llength $files] > 1} {puts -nonewline $file:}
puts $line
}
}
close $fp
}
}
# Test:
catch {console show}
puts "Result:\n[grep "require" "*.tcl"]"Here's another version - I wrote this out of desperation because the real grep -f ate up all my memory, and then busted, under Cygwin (remove the leading blank in the # line for an executable script):#!/usr/bin/env tclsh
proc main argv {
set usage {usage: grep-f.tcl refile ?file...? > outdata}
if {[llength $argv] < 1} {puts $usage; exit}
set fp [open [lindex $argv 0]]
set REset [split [string trim [read $fp]] \n]
close $fp
if {[llength $argv] == 1} {
grep-f $REset stdin
} else {
foreach file [lrange $argv 1 end] {
set fp [open $file]
grep-f $REset $fp
close $fp
}
}
}
proc grep-f {REset fp} {
while {[gets $fp line] >= 0} {
foreach RE $REset {
if {[regexp $RE $line]} {
puts $line
break
}
}
}
}
main $argvJM we can change the target-file selection to use wild cards (instead of listing each file) if we take some code from RS above: #!/usr/bin/env tclsh
proc main argv {
set usage {usage: grep-f.tcl refile ?file...? > outdata}
if {[llength $argv] < 1} {puts $usage; exit}
set fp [open [lindex $argv 0]]
set REset [split [string trim [read $fp]] \n]
close $fp
if {[llength $argv] == 1} {
grep-f $REset stdin
} else {
set files [eval glob -types f [lindex $argv 1]]
foreach file $files {
puts "============"
set fp [open $file]
grep-f $REset $fp
close $fp
}
}
}
proc grep-f {REset fp} {
while {[gets $fp line] >= 0} {
foreach RE $REset {
if {[regexp $RE $line]} {
puts $line
break
}
}
}
}
main $argv(this was moved here from Example Scripts Everybody Should HaveDKF: Grep does an awful lot of different things, and implementing a full version of it is probably a worthy topic for a Wiki page to itself. Here's something to get you started...
proc grep {pattern args} {
if {[llength $args] == 0} {
# read from stdin
set lnum 0
while {[gets stdin line] >= 0} {
incr lnum
if {[regexp $pattern $line]} {
puts "${lnum}:${line}"
}
}
} else {
foreach filename $args {
set file [open $filename r]
set lnum 0
while {[gets $file line] >= 0} {
incr lnum
if {[regexp $pattern $line]} {
puts "${filename}:${lnum}:${line}"
}
}
close $file
}
}
}FP: This slightly modified code is now included in Tcllibpackage require tcllib set listOfMatches [fileutil::grep $_pattern] ;# (stdin input) set listOfMatches [fileutil::grep $_pattern $_fileList]RS: Hmm.. I see duplication above... how about factoring that out, and make two little ones?
proc grep {pattern args} {
if {[llength $args] == 0} {
grep0 "" $pattern stdin
} else {
foreach filename $args {
set file [open $filename r]
grep0 ${filename}: $pattern $file
close $file
}
}
}
proc grep0 {prefix pattern handle} {
set lnum 0
while {[gets $handle line] >= 0} {
incr lnum
if {[regexp $pattern $line]} {
puts "$prefix${lnum}:${line}"
}
}
}DKF: Adjusted to print the filename too; that's usually useful with grep...ph: Small and simple.
proc grep {re {f stdin}} {
for {set i 0} {[gets $f line] >= 0} {incr i} {
if {[regexp $re $line]} {
puts "$i:$line"
}
}
}See Also edit
- Tcllib's fileutil::grep
- a grep-like utility
- A little file searcher
- with GUI
- Example Scripts Everybody Should Have
- Hits!

