#!/usr/bin/perl

use Cwd;
use Getopt::Long qw(GetOptions);

 $pgroup = getpgrp(0);
$curdir=cwd();
$curdir.="\/";
$start_at_block = $end_at_block =
$dir = $cat = $str_f = $rep_f = $opt_f = $str = $rep_str = 
$str3 = $first_str = $opt_dir = $str4 = $str1 = $str2 = $s_str = $s_rep_str = 
$rep_str4 = $del_line = $o_f = $rep_str3 = $rep_str1 = $rep_str2 = 
$s_str1 = $start_at_block = $end_at_block = $first_rep_str =$s_str2 =$s_str3 =$s_str4 =
$s_rep_str1 = $charlist =$s_rep_str2 = $s_rep_str3 = $s_rep_str4 =
$to_str = $from_end_str = $to_end_str = $start_block = $end_block = "";

$lfirst = $lines_to_1 =  $o_count = $ufirst = $upper = $lower = $tabs_to_spaces 
= $dos_ret = $i_count =
$all_lines = $rec = $start_line = $end_line = $leading_blanks = $dos = 0;

Getopt::Long::config ('bundling');
GetOptions(\%options, 'all_lines|a', 's_str=s', 'start_block=s', 'i_f=s',
's_str1=s', 'i_count|i', 'o_count|o', 's_str2=s', 's_str4=s', 's_str3=s',
's_rep_str4=s', 'charlist=s', 's_rep_str=s', 's_rep_str3=s', 's_rep_str1=s', 's_rep_str2=s',
'cat=s', 'first_str=s', 'first_rep_str=s', 'opt_dir=s', 'str1=s', 'str2=s', 'str4=s',
'rep_str4=s', 'dos_ret|o', 'str3=s', 'rep_str3=s', 'rep_str1=s', 'rep_str2=s',
'o_f=s', 'lines_to_1|n', 'opt_f=s', 'to_str=s',
'rep_str=s', 'dos|d', 'start_line=i', 'end_line=i', 'del_line=s', 'from_end_str=s',
'str_f=s', 'start_at_block=s', 'end_at_block=s', 'all_blanks|b', 'ign=s', 'dir=s', 'str=s', 
'end_block=s', 'to_end_str=s', 'rep_str=s', 'rep_f=s',
'leading_blanks=i', 'rec|r', 'tabs_to_spaces|s',
'lower|l', 'upper|u', 'lfirst|k', 'ufirst|t', 'help|h')
|| exit 1;
$opt_f=$options{opt_f};
$opt_dir=$options{opt_dir};
chdir($opt_dir) if $opt_dir ne "";
if (($opt_f ne "") && -f $opt_f){
$in_f=$opt_f;
open_in_f($in_f);
for($rn=0; $rn<=$#row; $rn++){
$_=$row[$rn];
$tmp = $_;
@array= split(//, $tmp);
next if $array[0] =~/#/;
$_ = $tmp;
print "$_\n";
$_=~s/\"//g;#remove the quotes from strings
if (s/--//){
if (s/str_f=//){
$str_f = $_;
next;}
if (s/rep_f=//){
$rep_f = $_;
next;}
if (s/cat=//){
$cat = $_;
next;}
if (s/charlist=//){
$charlist = $_;
next;}
if (s/s_str1=//){
$s_str1 =$_;
next;}
if (s/s_rep_str1=//){
$s_rep_str1 =$_;
next;}
if (s/s_str2=//){
$s_str2 =$_;
next;}
if (s/s_rep_str2=//){
$s_rep_str2 =$_;
next;}
if (s/s_str3=//){
$s_str3 =$_;
next;}
if (s/s_rep_str3=//){
$s_rep_str3 =$_;
next;}
if (s/s_str4=//){
$s_str4 =$_;
next;}
if (s/s_rep_str4=//){
$s_rep_str4 =$_;
next;}
if (s/s_str=//){
$s_str =$_;
next;}
if (s/s_rep_str=//){
$s_rep_str =$_;
next;}
if (s/first_str=//){
$first_str =$_;
next;}
if (s/first_rep_str=//){
$first_rep_str =$_;
next;}
if (s/i_f=//){
$i_f = $_;
next;}
if (s/o_f=//){
$o_f = $_;
next;}
if (s/from_end_str=//){
$from_end_str = $_;
next;}
if (s/to_str=//){
$to_str = $_;
next;}
if (s/to_end_str=//){
$to_end_str = $_;
next;}
if (s/rep_str2=//){
$rep_str2 = $_;
next;}
if (s/str2=//){
$str2 = $_;
next;}
if (s/rep_str1=//){
$rep_str1 = $_;
next;}
if (s/$str1=//){
$str1 = $_;
next;}
if (s/rep_str4=//){
$rep_str4 = $_;
next;}
if (s/$str4=//){
$str4 = $_;
next;}
if (s/rep_str3=//){
$rep_str3 = $_;
next;}
if (s/$str3=//){
$str3 = $_;
next;}
if (s/rep_str=//){
$rep_str = $_;
next;}
if (s/str=//){
$str = $_;
next;}
if (s/start_block=//){
$start_block = $_;
next;}
if (s/end_block=//){
$end_block = $_;
next;}
if (s/start_at_block=//){
$start_at_block = $_at_;
next;}
if (s/end_at_block=//){
$end_at_block = $_at_;
next;}
if (s/del_line=//){
$del_line = $_;
next;}
if (s/ign=//){
$ign = $_;
next;}
if (s/dir=//){
$dir=$_;
next;}
$lower = 1 if s/lower//;
$start_line = s/\D// if s/start_line//;
$end_line = s/\D// if s/end_line//;
$upper = 1 if s/upper//;
$lfirst = 1 if s/lfirst//;
$ufirst = 1 if s/ufirst//;
$lines_to_1 = 1 if s/lines_to_1//;
$i_count = 1 if s/i_count//;
$o_count = 1 if s/o_count//;
$all_lines = 1 if s/all_lines//;
$all_blanks = 1 if s/all_blanks//;
$dos = 1 if s/dos//;
$dos_ret = 1 if s/dos_ret//;
$tabs_to_spaces = 1 if s/tabs_to_spaces//;
$leading_blanks = $_ if s/leading_blanks=//;}#end of --
if (/-/){
$all_lines =1 if /a/;
$all_blanks =1 if /b/;
$tabs_to_spaces =1 if /c/;
$dos = 1 if /d/;
$dos_ret = 1 if /o/;
$lines_to_1 = 1 if /n/;
$lfirst =1 if /k/;
$lower =1 if /l/;
$rec = 1 if /r/;
$ufirst =1 if /t/;
$i_count =1 if /i/;
$o_count =1 if /o/;
$upper =1 if /u/;}#end of single character options
}#end of for
}#end of options  file
chdir($curdir) if $opt_dir ne "";
$i_f=$options{i_f} if $options{i_f} ne "";
$o_f=$options{o_f} if $options{o_f} ne "";#filespec for files if not used
$rep_str=$options{rep_str};#replacement string
$rep_str=$options{rs};#replacement string
usage() if (($options{help} ne "") && ($i_f eq ""));
$from_end_str=$options{from_end_str} if $options{from_end_str} ne "";
$str_f=$options{str_f} if $options{str_f} ne "";
$rep_f=$options{rep_f} if $options{rep_f} ne "";
$to_str=$options{to_str} if $options{to_str} ne "";
$to_end_str=$options{to_end_str} if $options{to_end_str} ne "";
$del_line=$options{del_line} if $options{del_line} ne "";#remove this line
if ($options{dir}){
$curdir="$options{dir}/";#input files may not have a path
chdir($curdir);}
$cat = $options{cat} if $options{cat} ne "";#cat files
$ign=$options{ign} if $options{ign} ne "";#ignore the line if string found
$charlist=$options{charlist} if $options{charlist} ne "";
$start_block=$options{start_block} if $options{start_block} ne "";
$end_block=$options{end_block} if $options{end_block} ne "";
$start_at_block=$options{start_at_block} if $options{start_at_block} ne "";
$end_at_block=$options{end_at_block} if $options{end_at_block} ne "";
$str4=$options{str4} if $options{str4} ne "";#str4ing to search for
$rep_str4=$options{rep_str4} if $options{rep_str4} ne "";#upper_replacement string
$str3=$options{str3} if $options{str3} ne "";#str3ing to search for
$rep_str3=$options{rep_str3} if $options{rep_str3} ne "";#rep_str3ing to replace
$str1=$options{str1} if $options{str1} ne "";#str1ing to search for
$rep_str1=$options{rep_str1} if $options{rep_str1} ne "";#lfirst_replacement string
$str2=$options{str2} if $options{str2} ne "";#ufirstlacement string
$rep_str2=$options{rep_str2} if $options{rep_str2} ne "";#ufirst_replacement string
$str=$options{str} if $options{str} ne "";#search string
$rep_str=$options{rep_str} if $options{rep_str} ne "";#replacement string
$s_str1=$options{s_str1} if $options{s_str1} ne "";#remove this str1
$s_rep_str1=$options{s_rep_str1} if $options{s_rep_str1} ne "";#remove this str1
$s_str2=$options{s_str2} if $options{s_str2} ne "";#remove this str2
$s_rep_str2=$options{s_rep_str2} if $options{s_rep_str2} ne "";#remove this str2
$s_str3=$options{s_str3} if $options{s_str3} ne "";#remove this str3
$s_rep_str3=$options{s_rep_str3} if $options{s_rep_str3} ne "";#remove this str3
$s_str4=$options{s_str4} if $options{s_str4} ne "";#remove this str4
$s_rep_str4=$options{s_rep_str4} if $options{s_rep_str4} ne "";#remove this str4
$s_str=$options{s_str} if $options{s_str} ne "";#remove this str
$s_rep_str=$options{s_rep_str} if $options{s_rep_str} ne "";#remove this str
$first_str=$options{first_str} if $options{first_str} ne "";#remove this str
$first_rep_str=$options{first_rep_str} if $options{first_rep_str} ne "";#remove this str
$rec = 1 if $options{rec};#recursive
$dos = 1 if $options{dos};#dos returns
$dos_ret = 1 if $options{dos_ret};#dos_ret returns
$lower=1 if $options{lower} ;
$lines_to_1=1 if $options{lines_to_1} ;
$all_lines=1 if $options{all_lines};
$all_blanks=1 if $options{all_blanks} ;
$upper=1 if $options{upper} ;
$lfirst=1 if $options{lfirst} ;
$ufirst=1 if $options{ufirst} ;
$i_count=1 if $options{i_count} ;
$o_count=1 if $options{o_count} ;
$tabs_to_spaces=1 if $options{tabs_to_spaces} ;
$start_line=$options{start_line} if $options{start_line} ;
$end_line=$options{end_line} if $options{end_line} ;
$leading_blanks=$options{leading_blanks} if $options{leading_blanks} ;
print "$curdir\n";
 foreach $_(keys %options ) {#list the options
printf "%s option = %s\n", $_, $options{$_}; }#end of foreach
 foreach $_(keys %options ) {#process the options
find_record() if $_ ne "";}#end of foreach
find_record() if $i_f ne "";
menu_list();
for (;;){#the main menu
$_ = $mp = "";
if ($case_val==1){
print "MENU>";}
elsif ($case_val==2){
print "menu>";}
else {
print ">";}
$menucall = 1;#allows for the Q or q selection
next if !query();
$menucall = 0;#q or q cause functions to return
$mp = uc($_);
$mp =~s/\s//g;
if ($mp eq 'V'){
&capture_list;}
elsif ($mp eq 'M'){
&menu_list;}
elsif ($mp eq 'I'){
&ignore;}
elsif ($mp eq 'Q'){
&quit;}
elsif ($mp eq 'R'){
&recursive;}
 elsif ($mp eq 'N'){
 &set_str;}
elsif ($mp eq '5'){
&my__view;}
elsif ($mp eq ')'){
&file_check;}
elsif ($mp eq '?'){
&usage;}
elsif ($mp eq '('){
&set_path;}
 else {
 print "Invalid command `$mp':";}
}#end of main

sub menu_list{#the menu after pressing m
print <<EOF;
   ?  help                              ) check the statistics of a file 
   5  display a file                    ( change user path for files
   m  this menu                         n  new search string 
   p  toggle case conversion            q  quit the program
   r  toggle recursive searches         i  string to ignore in searches
EOF
}#end of menu_list

sub usage{#option help for the program
print <<EOF;
stremove run in menu mode:
options single character options: --help | -h this message and exit
The options have their names as the scallar names 
--str becomes $str
--rep_str becomes $rep_str
--rep_str is the replacement for --str
$rep_str is the replacement for $rep_str
-s | --tabs_to_spaces a tab converts to 2 spaces
-r | --rec search recursively
--leading_blanks=2 reduce leading blanks to two characters
--i_count || -i count input characters in --charlist
--o_count || -o count output characters in --charlist
--charlist="()[]{}<>" list of characters for -o_count and i_count
--leading_blanks & --all_blanks & --i_count and --o_count slow the program
down because they require more processor time.
--all_lines | -a delete all blank lines
--lines_to_1 |-n reduce blank lines to 1
--all_blanks | -b delete all leading blanks
--lower | -l convert file to lower case
--upper | -u convert file to upper case
--lfirst | -t convert first character to lower case in word using lfirst()
--ufirst | -k convert first character to upper case in word using ufirst()
--dos | -d remove the returns from a file transfered from msdos
--dos_ret | -o replace the returns to a file transfered to msdos
--leading_blanks=2 leafve 1 .. num delete leading blanks
-- start_line=35 start processing at that line
--end_line=39 end processing at that line
The rest of the options do not have a single character option.
strings: These conform to the perl search /this is a string/ rules of perl.
--start_block="beginning of block"
--end_block="end of block" delete the block if --start_block and --end_block
--start_at_block="beginning of block"
--end_at_block="end of block" process the block if --start_at_block
and --end_at_block. The block is the output of the file.
if more than one block is found, it is included in the output.
if the block starts in the middle of the line you could:
--start_at_block="hello" --to_str="hello"
--end_at_block="good luck" --from_end_str="good luck"
The lines containing 'hello' and 'good luck' would be edited inside the block
if they are found.  --end_at_block and --start_block are queried before the
strings. --start_block and --end_block are queried last.
--del from_end_str="delete from beginning of this string to end of line"
--to_str="delete from beginning of line to the string"
--to_end_str="delete from beginning of line to the end of the string"
--ign="" Ignore the string ''.
the line containing this string will be ignored and left untouched. It is parsed aafter --start_line
--$str --str1 --str2 --str3 --str4="this is a string"
--$str is the first part of the s///g expression
--rep_str="this is a replacement string"
--rep_str --rep_str1 --rep_str2 --rep_str3 --rep_str4="replace strings"
--rep_str is the send part of the s///g expression
replacement strings are optional
 --s_str="remove" s/// expression
-s_rep_str s///  replace expression
 --first_str="remove" s/// expression
-first_rep_str s///  replace expression
--s_str1 --s_str2 --s_str3 --s_str4
--s_rep_str1 --s_rep_str2 --s_rep_str3 --s_rep_str4
s/// expression

file / directory options:
--i_f="*" --i_f="filename" is an esential option, otherwise the program
exits after giving you this message.
--i_f must be on the command line or in the options file --opt_f
--dir="/home" Start in the directory '/home'.
--$str_f="words.txt" A file to use for multiple global searches.
--rep_f="replace_words" A file to use for replacing strings.
--opt_f="stremove.opt" file with command line options.
--opt_dir="/home/barryp" the directory for --opt_f --$str_f --rep_f
if --opt_dir is used the program expects the string files to be in the same
directory as the options file. You may have one or two options if you are 
using the options file. --i_f is required on the command line or in the
options file. lines containing a '#' are skipped in the options file.
The command line takes presidence over --opt_f.
--i_f="input file"
--o_f="output file"
the output filespec should be different than the --i_f
because of the wildcard /recursive capability.
Output files are written in the same directory as the input files.
--i_f is esential. Use either --cat or --o_f.
This means that the file ending should be different.
You should not use wildcards in --i_f if --o_f is used.
If you use a string file, --str_f requires --rep_f if you wish to replace
strings.
If there are no replacements:
all lines will contain 2 characters. 
--rep_f cannot have more valid lines than --$str_f.
if you had a string file that looks like this:
#string file
'= = = "
"- - - "
Notice the delimiters for the strings in the --str_f="text" and rep_f="junk"
do not have to be the same because the program shifts off the first character
and it chops off the last character.
now the replacement file
#this is a replacement file
'x
pthe dashes are gone '

the first string is deleted.
the second string is replaced.

Keep in mind that strings must conform to the s/// rules of perl.
Meta characters should be breceeded with a '\'
therefore:
--str="\/\*"

The program uses the perl glob() command to create a directory list.
if --cat is used to concatinate the output, a new cat file is created if
--rec | -r is used, and another directory is found.
--cat creates a new concatination file for each directory.
Lines beginningwith a # '#' are comment lines in the options file, the string
file and the replacement string file.

a command line :
stremove --opt_dir="/home/barryp/keyspk" --opt_f="stremove.opt"
options file:
# stremove options file
# 1 option per line
# single character options must be preceded by a - ie -s
# -r
#-l
#single character options may not be grouped
#1 option per line
#all lines starting a '#' are ignored
--i_f="*"
--cat="book"
--tabs_to_spaces
--leading_blanks=2
--all_lines
--$str_f="string.opt"
#the string file will be located in the same directory as the options file

Search for the string in text files in the current directory and below or change
 to a directory in --dir. The process number is $pgroup
Use p or P to toggle the case setting at the prompts.
0 off, 1 convert to upper case, 2 convert to lower case.
Character conversion is disabled for file names but it is activated
when the pathe or file name is completed.
The case of `MENU' at the menu prompt shows the status of case conversion. The
input line appears again in its converted form if case conversion is active.
The menu prompt shows a `>' when case conversion is disabled.
If you choose n or N from the menu, you may leave the string blank if you
do not desire that choice.
EOF
quit() if $options{help};
}#end of usage

sub error_f{#try to recover from a file error
print "Is this an input or output file ?(I, O)\n";
return if !query();
$tmp = uc($_);
print "Now the File Name:\n";
$tbl=1;
return if (!(&ans()));
$tbl=0;
if ($tmp eq 'O'){
$out_f = $answer;
&cap_f;}
else {
$in_f = $answer;}
$tbl;}#end of error_f

sub cap_f{#choose append or create for files
$tmp=$no_err;
$no_err=0;
print "Create a new fild or append a current file?(C, A)\n";
return if !query();
$cap = uc($_);
print "Enter the file name to save, and press enter\n";
return if !($out_f=&ans());
$no_err=$tmp;
return($cap,$out_f);}#end of cap_f

sub check_exist{#check and open an output file not used in batch mode
print "Replace $out_f?(Y, N)" if -e $out_f;
&query() if -e $out_f;
if (uc($_) eq 'Y'){ 
unlink $out_f;}
if ($mp ne '7'){
 unless(open(FH, ">$out_f")){
 warn("cannot open the output file $out_f\n");
&error_f;}
}
}#end of check_exist

sub query{#the input line
$_ = <STDIN>;
chomp($_);
if ($_ eq 'p' || $_ eq 'P'){
&case;
return if !query();}
if (length($_)){
if ($case_val==1){
tr/a-z/A-Z/;}
if ($case_val==2){ 
tr/A-Z/a-z/;}
}#end of length
if (uc($_) eq 'Q' && !$menucall){
return($_ = $mp = "");}
print "$_\n" if $case_val;
quit() if uc($_) eq 'QUIT';
$_;}#end of query

sub open_in_f{#open an input file
undef @row;
 unless(open(IN_FILE, "$in_f")){
 warn("cannot open the input file\n$in_f\n");
&error_f;}
print "loading $in_f\n" if -f $in_f && ! $i_f;
 @row = <IN_FILE>;
close(IN_FILE);
chomp(@row);
return($in_f,@row);}#end of open _in_f

#Display the subdirectories of the current directory and the menu options.
sub file_check{#what type of file
 print "Enter the name of the file to check:\n";
$name = &ans();
($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
 $atime, $mtime, $ctime, $blksize, $blocks) = stat("$name");
print("dev = $dev\n");
print("ino = $ino\n");
print("mode = $mode\n");
print("nlink = $nlink\n");
print("uid = $uid\n");
print("gid = $gid\n");
print("rdev = $rdev\n");
print("size = $size\n");
print("atime = $atime\n");
print("mtime = $mtime\n");
print("ctime = $ctime\n");
print("blksize = $blksize\n");
print("blocks = $blocks\n");
if (-l $name){
lstat($name);
} else {
stat($name);}
 print "Testing flags for $name \n";#looking for wc
chdir "/usr/bin";
if (-x "wc"){
print " Lines Words Characters	Name\n";
$wc = "|wc $name";
unless(open(MH, "$wc")){
warn("Can't open wc with $name\n");}
close($MH);}
system "ls -l $name";
 print "\n is readable" if ( -r $name);
 print "\n is writable" if ( -w $name);
 print "\n is executable" if ( -x $name);
 print "\n is owned " if ( -o $name);
 print "\nReal User ID tests ";
 print "\n is readable" if ( -R $name);
 print "\n is writable" if ( -W $name);
 print "\n is executable" if ( -X $name);
$tmp = -O $name;
 print "\n is owned by group $tmp " if ( -O $name);
 print "\nReality Checks ";
 print "\n is a file " if (-f $name);
 print " that exists " if ( -e $name);
 print " has zero bytes " if ( -z $name);
if ($tmp = -s $name){
 print " has $tmp bytes in it\n" if ( -s $name);
 print "\n is a Text file " if (-T $name);}
 print "\n is a directory " if (-d $name);
 print "\n is a link " if (-l $name);
 print "\n is a socket " if (-S $name);
 print "\n is a pipe " if (-p $name);
 print "\n is a block device " if (-b $name);
 print "\n is a character device " if (-c $name);
 print "\n has setuid bit set " if (-u $name);
 print "\n has sticky bit set " if (-k $name);
 print "\n has gid bit set " if (-g $name);
 print "\n is open to terminal " if (-t $name);
 print "\n is a Binary file " if (-B $name);
return("") if !query();
 return("");}#end of file_check

sub ans{#ask for a case sensitive request
$xt=$case_val;
$case_val=0;
print
"\nThis is a case sensitive request, your previous case setting will be restored.\n"
if $xt>=1;
$answer=&query();
$_=$answer;
$case_val=$xt;#return to the previous case setting
$answer;}#end of ans

sub ret{#an enter prompt
print"Press enter:";
&query;}#end of ret
sub quit{#quit the program
die "Thank you for using $0.\n";}#end of quit

sub set_path{#set a directory path
for (;;){
print "Enter the absolute path for your files with the trailing /:\n";
$tbl=1;
next if !&ans();
$userpath = $_;
$tbl=0;
chdir($userpath) if -d $userpath;
last if -d $userpath;}#end of loop
$userpath;}#end of set_path

sub my__view{#view a file
print "Enter the file name to view.\n";
&load;
for ($ct = 0,$tmp = 0; $ct <= $#row; $ct++, $tmp++){
print "$row[$ct]\n";
last if $_ eq "";
if ($tmp == 19){
$tmp = -1;
next if !query();
ret();}
}#end of for
}#end of my__view

sub load{#an input file
$tmp=$no_err;
$no_err =0;
return if (!($in_f=&ans()));
$no_err=$tmp;
&open_in_f($in_f);}#end of load

sub recursive{#toggle recursive search -r
if ($rec==1){
$rec = 0;
print " recursive search is disabled.\n";}
else {
$rec = 1;
print "Recursive search is now active.\n";}
$rec;}#end of recursive

sub ignore{#a string to ignore
print "Enter your string of characters to be ignored in searches:\n";
return if !query();
$ign = &ans();}#end of ignore


sub set_str(){#set a search string
print "Enter your string to remove:\n";
return if !query();
$str = $_;
print "Enter your replacement string:\n";
return if !query();
$rep_str = $_;
print "Enter the input file name to change:\n";
return if !query();
$i_f=$_;
print "Enter the output file name:\n";
return if !query();
$o_f=$_;
find_record();}#end of set_str

sub file_open{#open files
if (($cat ne "") || ($o_f ne"")){
 unless(open(IN_FILE, "$in_f")){
 warn("cannot open the input file\n$in_f\n");
&error_f;}
}#end of if
else {#we overwrite the file less efficent because we must use @row
$o_f = $in_f;
open_in_f($in_f);}#end of input file
if ($cat ne "" ){
 unless(open(FH, ">>$cat")){
 warn("cannot open the output file $cat\n");
&error_f;}
}
if ($o_f ne ""){
unlink($o_f) if -e $o_f;
 unless(open(FH, ">$o_f")){
 warn("cannot open the output file $o_f\n");
&error_f;}
}
$o_f = "" if $in_f eq $o_f ;
print "$o_f\n" if $o_f ne "";}#end of file_open

sub find_record{#find records in text files
$beg = $end = $rb = $file_count = $block_count = $blank_count = $tab_count = 0;
$end_block_len=length($end_block);
$to_end_str_len=length($to_end_str);
$from_end_str_len=length($from_end_str);
set_str() if ($str eq "") && ($i_f eq "");
if ($str_f ne ""){
chdir($opt_dir) if $opt_dir ne "";
$a=0;
$in_f=$str_f;
open_in_f($in_f);
for ($rn=0; $rn <=$#row; $rn++){
$_=$row[$rn];
chop $_;
@array= split(//, $_);
next if $array[0] =~/#/;
$_="";
for ($c=1; $c<=$#array; $c++){
$_ .= $array[$c];}
$array_str[$a]=$_;
$a++;}#end of for
close(IN_FILE);
if ($rep_f ne ""){
$a=0;
chdir($opt_dir) if $opt_dir ne "";
$in_f=$rep_f;
open_in_f($in_f);
for ($rn=0; $rn <=$#row; $rn++){
$_=$row[$rn];
chop $_;
@array= split(//, $_);
next if $array[0] =~/#/;
$_="";
for ($c=1; $c<=$#array; $c++){
$_ .= $array[$c];}
$array_rep[$a]=$_;
$a++;}#end of for
close(IN_FILE);}#end of if
chdir($curdir) if $opt_dir ne "";}#end of if
if ($charlist ne ""){#count characters
@chl= split(//, $charlist);
for ($c=0; $c <= $#chl; $c++){
$ich[$c]=0;
$och[$c]=0;
$chl[$c]="\\$chl[$c]";}#end of for
}#end of if
if ($leading_blanks || $all_blanks){
$blank =" " if $all_blanks;
if ($leading_blanks > 0){
$blank ="";
for ($c=0; $c< $leading_blanks; $c++){
$blank .= " ";}#end of for
}#end of if 
}#end of if
$i_f="*" if $rec ==1;#this must b * for recursive searches
$i = $c = $x = $in_count = $out_count = $str_count = 0;
$userpath=$curdir if $dir ne "";
$directorycount=1;
for (;;){
print "concatinating $cat\n" if $cat ne "";
@file_list = glob($i_f);
for($ct = 0; $ct <= $#file_list; $ct++){
$in_f = $file_list[$ct];
next if ($in_f =~ /$cat/) && ($cat ne "");
if ((-d $in_f) && $rec){#recursive
$dir_list[$i]="$userpath$in_f/";
$i++;
next;}#end of if 
if ( -T $in_f){
$file_count++;
file_open();
$rn = $rb = $spb = $fs = 0;#for blocks and first string of file
print "$in_f\n";
if (($cat ne "") || ($o_f ne"")){
while (<IN_FILE>){
chomp $_;
next if ($start_line > $rn) && ($start_line > 0);
last if ($rn ==$end_line) && ($end_line > 0);
$rn ++;
s/\r//g if $dos == 1;#remove returns
if ($_ ne ""){#not a blank line
if ($i_count && ($charlist ne "")){
@array=split(//, $_);
for ($c=0; $c<=$#chl; $c++){
if (/$chl[$c]/){
for ($f=0; $f<=$#array;$f++){
$ich[$c]++ if ($array[$f] =~/$chl[$c]/);}#end of for
}#end of if
}#end of for
}#end of if
$lc=0;#the line is not blank
if (($ign ne "") && (/$ign/)){# this line stays
$out_count++;
if ($dos_ret){
print FH "$_\r\n";
} else {
print FH "$_\n";}
next;}
if (($start_at_block ne "") && ($end_at_block ne "")){
if (($spb == 0) && ($start_at_block ne "") && (/$start_at_block/)){
$spb++;
$block_count++;}
next if $spb==0;
if (($spb == 1) && ($end_at_block ne "") && (/$end_at_block/)){
$spb=0;}
}#end of if
if (($fs == 0) && ($first_str ne "") && (/$first_str/)){#1 string search/replaced in file
$fs++;
s/$first_str/$first_rep_str/;
$str_count++;}
if (($del_line ne "") && (/$del_line/)){# this line goes
next;}
if ($rep_f ne ""){
for ($c=0; $c <= $#array_rep; $c++){
$rep_count++ if s/$array_str[$c]/$array_rep[$c]/g;
last if length($_) == 0;}#end of for
next if length($_) == 0;}#end of if
elsif ($str_f ne ""){
for ($c=0; $c <= $#array_str; $c++){
$str_count++ if s/$array_str[$c]//g;
last if length($_) == 0;}#end of for
next if length($_) == 0;}#end of if
search($_);}#end of $_ ne ""
else {#it is a blank line
next if (($spb == 0) && ($start_at_block ne "") && ($end_at_block ne ""));
next if $all_lines == 1;
if ($lines_to_1) {#reduce blank lines to 1
$lc++;
if ($lc == 1){
print_line();
next;}
next if $lc >1;}#end of lines_to_1
next if $rb ==1;}
print_line();}#end of while
close(IN_FILE);}
else {# less efficient
for ($rc=0; $rc<=$#row; $rc++){
$_=$row[$rc];
next if ($start_line > $rn) && ($start_line > 0);
last if ($rn ==$end_line) && ($end_line > 0);
$rn ++;
s/\r//g if $dos == 1;#remove returns
if ($_ ne ""){#not a blank line
if ($i_count && ($charlist ne "")){
@array=split(//, $_);
for ($c=0; $c<=$#chl; $c++){
if (/$chl[$c]/){
for ($f=0; $f<=$#array;$f++){
$ich[$c]++ if ($array[$f] =~/$chl[$c]/);}#end of for
}#end of if
}#end of for
}#end of if
$lc=0;#the line is not blank
if (($ign ne "") && (/$ign/)){# this line stays
$out_count++;
if ($dos_ret){
print FH "$_\r\n";
} else {
print FH "$_\n";}
next;}
if (($start_at_block ne "") && ($end_at_block ne "")){
if (($spb == 0) && ($start_at_block ne "") && (/$start_at_block/)){
$spb++;
$block_count++;}
next if $spb==0;
if (($spb == 1) && ($end_at_block ne "") && (/$end_at_block/)){
$spb=0;}
}#end of if
if (($fs == 0) && ($first_str ne "") && (/$first_str/)){#1 string search/replaced in file
$fs++;
s/$first_str/$first_rep_str/;
$str_count++;}
if (($del_line ne "") && (/$del_line/)){# this line goes
next;}
if ($rep_f ne ""){
for ($c=0; $c <= $#array_rep; $c++){
$rep_count++ if s/$array_str[$c]/$array_rep[$c]/g;
last if length($_) == 0;}#end of for
next if length($_) == 0;}#end of if
if ($str_f ne ""){
for ($c=0; $c <= $#array_str; $c++){
$str_count++ if s/$array_str[$c]//g;
last if length($_) == 0;}#end of for
next if length($_) == 0;}#end of if
search($_);}#end of $_ ne ""
else {#it is a blank line
next if (($spb == 0) && ($start_at_block ne "") && ($end_at_block ne ""));
next if $all_lines == 1;
if ($lines_to_1) {#reduce blank lines to 1
$lc++;
if ($lc == 1){
print_line();
next;}
next if $lc >1;}#end of lines_to_1
next if $rb ==1;}
print_line();}#end of for
}#end of else
close(FH);}#end of if
$in_count+=$rn;}#end of for
last if $x == $i;
$directorycount++;
$userpath=$dir_list[$x];
chdir($dir_list[$x]) if ($i > $x);
$x++ if ($i > $x);}#end of directory
print "$str_count lines with strings.\n" if $str_count;
print "$block_count blocks.\n" if $block_count;
print "$directorycount directories $file_count files $in_count input lines $out_count output lines\n" if $in_count;
print "$tab_count tabs.\n" if $tab_count;
print "$blank_count lines with blanks.\n" if $blank_count;
if (($i_count || $o_count) && $charlist ne ""){
for ($c=0, $f=0; $c <=$#chl; $c++){
if ($i_count ){
printf("%s %-10ld ", $chl[$c], $ich[$c]);
print "\n" if ($f % 5 == 0) && $f != 0;
$f=0 if $f == 5;
$f++;}#end of if
if ($o_count ){
printf("%s %-10ld ", $chl[$c], $och[$c]);
print "\n" if ($f % 5 == 0) && $f != 0;
$f=0 if $f == 5;
$f++;}#end of if
}#end of for
print "\n";}#end of if
chdir($curdir);
quit() if $i_f ne "";}#end of find_record

sub print_line{#send the line to the file
my($c, $f);
$_=lfirst($_) if $lfirst ==1;
$_=ufirst($_) if $ufirst ==1;
$_=lc($_) if $lower ==1;
$_=uc($_) if $upper ==1;
if (($tabs_to_spaces == 1 && /\t/)){
$tab_count++;
s/\t/  /g;}#end of if 
if ((($blank ne "") && ($_ ne "")) || ($o_count && ($charlist ne ""))){
@array= split(//, $_);
if (/$blank/ && ($all_blanks || ($leading_blanks > 0))){ #0 disables
for ($c=0; $c <=$#array; $c++){
last if $array[$blank] ne " ";
if ($leading_blanks > 0){
last if $c == $leading_blanks;
shift(@array);}
elsif ($all_blanks  == 1) {
shift(@array);}
}#end of for
$blank_count++ if $c > 0;
$_=join("", @array);}#end of leading_blanks
if (($_ ne "") && $o_count && ($charlist ne "")){
for ($c=0; $c<=$#chl; $c++){
if (/$chl[$c]/){
for ($f=0; $f<=$#array;$f++){
$och[$c]++ if ($array[$f] =~/$chl[$c]/);}#end of for
}#end of if
}#end of for
}#end of if
}#end of if
$out_count++;
if ($dos_ret){
print FH ("$_\r\n");}
else {
print FH ("$_\n");}
next;}#end of print_line

sub search($_){#s/// | s///g
if (($s_rep_str ne "") && (/$s_rep_str/)){#1 rep_string search/replaced
s/$s_str/$s_rep_str/;
$str_count++;}
elsif (($s_str ne "") && (/$s_str/)){#1 string search/replaced
s/$s_str//;
$str_count++;}
if (($s_rep_str1 ne "") && (/$s_rep_str1/)){#1 rep_str1ing search/replaced
s/$s_str1/$s_rep_str1/;
$str_count++;}
elsif (($s_str1 ne "") && (/$s_str1/)){#1 str1ing search/replaced
s/$s_str1//;
$str_count++;}
if (($s_rep_str2 ne "") && (/$s_rep_str2/)){#2 rep_str2ing search/replaced
s/$s_str2/$s_rep_str2/;
$str_count++;}
elsif (($s_str2 ne "") && (/$s_str2/)){#2 str2ing search/replaced
s/$s_str2//;
$str_count++;}
if (($s_rep_str3 ne "") && (/$s_rep_str3/)){#3 rep_str3ing search/replaced
s/$s_str3/$s_rep_str3/;
$str_count++;}
elsif (($s_str3 ne "") && (/$s_str3/)){#3 str3ing search/replaced
s/$s_str3//;
$str_count++;}
if (($s_rep_str4 ne "") && (/$s_rep_str4/)){#4 rep_str4ing search/replaced
s/$s_str4/$s_rep_str4/;
$str_count++;}
elsif (($s_str4 ne "") && (/$s_str4/)){#4 str4ing search/replaced
s/$s_str4//;
$str_count++;}#global strings
if (($rep_str ne "") && (/$rep_str/)){
s/$str/$rep_str/g;
$str_count++;}
elsif (($str ne "") && (/$str/)){
s/$str//g;
$str_count++;}
if (($rep_str1 ne "") && (/$rep_str1/)){
s/$str1/$rep_str1/g;
$str_count++;}
elsif (($str1 ne "") && (/$str1/)){
s/$str1//g;
$str_count++;}
if (($rep_str2 ne "") && (/$rep_str2/)){
s/$str2/$rep_str2/g;
$str_count++;}
elsif (($str2 ne "") && (/$str2/)){
s/$str2//g;
$str_count++;}
if (($rep_str3 ne "") && (/$rep_str3/)){
s/$str3/$rep_str3/g;
$str_count++;}
elsif (($str3 ne "") && (/$str3/)){
s/$str3//g;
$str_count++;}
if (($rep_str4 ne "") && (/$rep_str4/)){
s/$str4/$rep_str4/g;
$str_count++;}
elsif (($str4 ne "") && (/$str4/)){
s/$str4//g;
$str_count++;}
if ((/$to_str/) && ($to_str ne "")){
$beg= index($_, $to_str);
$_=substr($_, $beg);
$str_count ++;
next if $_ eq "";
print_line();}
if (($to_end_str ne "") && (/$to_end_str/)){
$beg= index($_, $to_end_str);
$end=($beg + $to_end_str_len);
$_=substr($_, $end);
$str_count ++;
next if $_ eq "";
print_line();}
if (($from_end_str ne "") && (/$from_end_str/)){
$beg= index($_, $from_end_str);
$end=($beg + $from_end_str_len);
$_=substr(0,$_, $end);
$str_count++;
next if $_ eq "";
print_line();}
if ($rb == 0 && ($start_block ne "") && (/$start_block/)){
$beg= index($_, $start_block);
if ((/$end_block/) && ($end_block ne "")){
$tmp=substr($_, 0,$beg);
$beg= index($_, $end_block);
$end=($beg + $end_block_len);
$a=$_;
$a=substr($a, $end);
$_=$tmp.$a;#$beg to $end is now gone.
$rb=0;#becomes 0 if end of block is reached
print_line();}
else {#a multi line block
$_=substr($_, 0,$beg);
$rb=1;#becomes 0 if end of block is reached
$block_count++;
print_line();}
}
if ($rb== 1 && (/$end_block/) && ($end_block ne "")){
$beg= index($_, $end_block);
$end=($beg + $end_block_len);
$_=substr($_, $end);
$rb=0;#end of block is reached
print_line();}
if ($rb == 1){#remove this line in the block
next;}#end of rm
$_;}#end of search

1;
