# Ussage # # "Find what" field : this can either by a piece of text that will be searched for LITERALY, CASE SENSITIVELY # or a Perl regular expression. The script will treat the parameter as a regexp only if it looks like # a regular expression in a Perl script. That is : # /regexp/options # m{regexp}options - you can use any kind of braces, (), {}, <> or {} # m#regexp#options - you can use any non-brace character # If you don't need to pass any options you can write the regexp like this : # / regexp - the spaces between the slash and the regexp will be deleted in this case # # you can even do a search replace if you enter : # s/regexp/replacement/options # s{regexp}{replacement}options - you can use any kind of braces, (), {}, <> or {} # s#regexp#replacement#options - you can use any non-brace character # If you add an exclamation mark at the end of the field, then the replacement will be done automaticaly, # otherwise you will be asked for each line. # BE VERY CAREFULL WITH THE EXCLAMATION MARK !!! # # "Files" field : this can either be a space or comma separated list of wildcards or a regexp in format # /regexp/opt # The other regexp formats allowed in "Find what" field are NOT supported ! # # # Written by Jenda@Krynicky.cz (c) 2001 # This program is free. #use G; # the G module may be downloaded from http://jenda.krynicky.cz/#G # it allows you to quote the parameters to Perl scripts almost exactly like under Unix # It even allows using backticks : script.pl `dir /B /A-D` # # If you don't use G.pm set find.command in Global.properties to : # find.command=c:\perl\bin\perl.exe c:\soft\wscite\SciteFind.pl "$(find.what)" "$(find.files)" # # if you do use G.pm (recomended) set the option to : # find.command=c:\perl\bin\perl.exe c:\soft\wscite\SciteFind.pl '$(find.what)' '$(find.files)' # # In the first case you'll have to escape doublequotes in the second singlequotes by a backslash # in the search pattern (and in the Files filter regular expression). use strict; use Cwd; use File::Find; use File::Copy; our $VERSION = '3.0'; our $pattern = shift; our $files = shift; our $patternRE; our $filesRE = makeFileFilter( $files); our $replacement; our $global = 0; if ($pattern =~ m{^/.*/\w*$}) { $patternRE = eval "qr".$pattern; die "Invalid search regexp $pattern : $@\n" if $@; find(\&find_it, cwd()); } elsif ($pattern =~ s{^/\s*}{/}) { $patternRE = eval "qr".$pattern.'/'; die "Invalid search regexp $pattern/ : $@\n" if $@; find(\&find_it, cwd()); } elsif ($pattern =~ m'^m([^<({[]).*\1\w*$' or $pattern =~ m'^m\[.*\]\w*$' or $pattern =~ m'^m<.*>\w*$' or $pattern =~ m'^m{.*}\w*$' ) { $patternRE = eval "qr".substr($pattern,1); die "Invalid search regexp $pattern : $@\n" if $@; find(\&find_it, cwd()); } elsif ($pattern =~ m'^s(([^<({[]).*?\2)(.*?)\2(\w*)\s*(!?)$' or $pattern =~ m'^s(\[.*?\])\[(.*?)\](\w*)\s*(!?)$' or $pattern =~ m'^s(<.*?>)<(.*?)>(\w*)\s*(!?)$' or $pattern =~ m'^s({.*?}){(.*?)}(\w*)\s*(!?)$' ) { # search&replace my ($pattern,$options,$confirm); if (defined $5) { ($pattern,$replacement,$options,$confirm) = ($1,$3,$4,$5); } else { ($pattern,$replacement,$options,$confirm) = ($1,$2,$3,$4); } # print "Search & Replace:\n\tsearch: m$pattern$options\n\treplace: $replacement\n\n"; $global = 1 if $options =~ s/g//g; $patternRE = eval "qr".$pattern.$options; die "Invalid search regexp $pattern : $@\n" if $@; $replacement = qq{<<"*E*/òD^+*"\n$replacement\n*E*/òD^+*\n}; $|=1; if ($confirm eq '!') { find(\&replace_it, cwd()); } else { find(\&replaceConfirm_it, cwd()); } } else { $patternRE = qr/\Q$pattern\E/; find(\&find_it, cwd()); } sub find_it { return if -d; return unless /$filesRE/; my $file = $_; my $dir = $File::Find::dir; $dir =~ s{/}{\\}g; if (! open IN, '<'.$file) { print "Can't open file $dir\\$file : $!\n"; return; } while () { if (/$patternRE/) { print "Found at $dir\\$file line $.\n\t$_\n"; } } close IN; } sub replace_it { return if -d; return unless /$filesRE/; my $file = $_; my $dir = $File::Find::dir; $dir =~ s{/}{\\}g; if (! open IN, '<'.$file) { print "Can't open file $dir\\$file : $!\n"; return; } if (! open OUT, '>'.$file.'.tmp') { print "Can't open file $dir\\$file.tmp : $!\n"; return; } while () { chomp; my $line = $_; if ($global and s/$patternRE/"substr $replacement, 0, -1"/gee or s/$patternRE/"substr $replacement, 0, -1"/ee ) { print "Found and replaced at $dir\\$file line $.\n\t$line\n\t\t\t=>\n\t$_\n"; } print OUT $_,"\n"; } close IN; close OUT; unlink $file; move "$file.tmp" => $file; } sub replaceConfirm_it { return if -d; return unless /$filesRE/; my $file = $_; my $dir = $File::Find::dir; $dir =~ s{/}{\\}g; if (! open IN, '<'.$file) { print "Can't open file $dir\\$file : $!\n"; return; } if (! open OUT, '>'.$file.'.tmp') { print "Can't open file $dir\\$file.tmp : $!\n"; return; } while () { chomp; my $line = $_; if ($global and s/$patternRE/"substr $replacement, 0, -1"/gee or s/$patternRE/"substr $replacement, 0, -1"/ee ) { my $replacedline = $_; $replacedline =~ s/\n/\n\t/g; print "Found pattern at $dir\\$file line $.\n\t$line\n\t\t\t=>\n\t$replacedline\nReplace? ([y]es/[N]o/[s]kip file/e[x]it) "; my $res = lc(); chomp $res; if ($res eq 'y') { print "Replaced!\n\n"; print OUT $_,"\n"; } elsif ($res eq 'x') { print "EXIT!\n\n"; unlink "$file.tmp"; exit(); } elsif ($res eq 's') { print "SKIP FILE!\n\n"; unlink "$file.tmp"; return; } else { print "Skipped\n\n"; print OUT $line,"\n"; } } else { print OUT $_,"\n"; } } close IN; close OUT; unlink $file; move "$file.tmp" => $file; } sub makeFileFilter { my $files = shift; if (substr($files, 0, 1) eq '/') { my $RE = eval "qr".$files; die "Invalid filename filter regexp $files : $@\n" if $@; return $RE; } else { my $RE; my @wilds = split /[ ,]/, $files; foreach my $wild (@wilds) { $wild =~ s/([.+])/\\$1/g; $wild =~ s/\*/.*/g; $wild =~ s/\?/./g; $RE .= $wild.'|'; } chop $RE; return qr/^(?:$RE)$/; } }