Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > File edits in a Perlish way

Reply
Thread Tools

File edits in a Perlish way

 
 
pgodfrin
Guest
Posts: n/a
 
      09-29-2008
I have a need to pass a series of "edits" I'd like to apply in a
somewhat controlled manner.

My pseudo code would be something like:
1. accept as input the file name, old text, new text
2. check existence in file for old text, if not found error out
3. if found, then show before and after text for the whole line
4. Write out file.

I'm currently using @ARGV for #1 and I intend to slurp the whole file
into an array and then use map for #4.

I'm looking for ideas on a "perlish" way to do #2 and #3. The grep
function lets me show before and after like so:

print grep(/$oldtx/,@oldfile);

But I haven't checked for existence of the $oldtx as of yet. so a type
would make this print statement print nothing. I could always use
loops and other brute force methods - but it seems like there may be a
cooler, perlish way to this... Any ideas?
phil
 
Reply With Quote
 
 
 
 
cartercc
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 1:08*pm, pgodfrin <(E-Mail Removed)> wrote:
> 1. accept as input the file name, old text, new text


print "Enter file name:";
my $filename = <STDIN>;
chomp $filename;
print "Enter old text:";
my $oldtext = <STDIN>;
chomp $oldtext;
print "Enter new text:";
my $newtext = <STDIN>;
chomp $newtext;

> 2. check existence in file for old text, if not found error out


open INFILE, "<$filename" or die "INFILE ERROR, $!";
open OUTFILE, ">outfile.txt" or die "OUTFILE ERROR, $!";

> 3. if found, then show before and after text for the whole line
> 4. Write out file.


while(<INFILE>)
{
print OUTFILE if /$oldtext/;
# maybe this as well ...
# next unless /$oldtext/;
# $_ = s/$oldtext/$newtext/;
# print;
}
close INFILE;
close OUTFILE;

CC
 
Reply With Quote
 
 
 
 
Jürgen Exner
Guest
Posts: n/a
 
      09-29-2008
pgodfrin <(E-Mail Removed)> wrote:
>I have a need to pass a series of "edits" I'd like to apply in a
>somewhat controlled manner.


Are those edits limited to one line at a time(a) or can a single edit
spread across multiple lines(b) ?

>My pseudo code would be something like:
>1. accept as input the file name, old text, new text
>2. check existence in file for old text, if not found error out
>3. if found, then show before and after text for the whole line
>4. Write out file.
>
>I'm currently using @ARGV for #1


Ok

>and I intend to slurp the whole file into an array


If (a) then ususally it is better to process the file line by line
instead of slurping it in all at once.
If (b) then manipulating the file in memory is probably easier.

>and then use map for #4.


Most people would use print() to write something.

>I'm looking for ideas on a "perlish" way to do #2


perldoc -f index

>and #3.


if (index($line, $oldtext) > -1) {
print $line;
apply_edit($line, $oldtext, $newtext);
print $line
}

>The grep
>function lets me show before and after like so:
>
> print grep(/$oldtx/,@oldfile);
>
>But I haven't checked for existence of the $oldtx as of yet. so a type
>would make this print statement print nothing.


I have no idea what you are trying to do with that code snippet. It
doesn't look like anything related to "show before and after text"

jue
 
Reply With Quote
 
Ron Bergin
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 10:08 am, pgodfrin <(E-Mail Removed)> wrote:
> I have a need to pass a series of "edits" I'd like to apply in a
> somewhat controlled manner.
>
> My pseudo code would be something like:
> 1. accept as input the file name, old text, new text
> 2. check existence in file for old text, if not found error out
> 3. if found, then show before and after text for the whole line
> 4. Write out file.
>
> I'm currently using @ARGV for #1 and I intend to slurp the whole file
> into an array and then use map for #4.
>
> I'm looking for ideas on a "perlish" way to do #2 and #3. The grep
> function lets me show before and after like so:
>
> print grep(/$oldtx/,@oldfile);
>
> But I haven't checked for existence of the $oldtx as of yet. so a type
> would make this print statement print nothing. I could always use
> loops and other brute force methods - but it seems like there may be a
> cooler, perlish way to this... Any ideas?
> phil


Do you want the output to go to a new file, or simply edit/update the
source file?

If outputting to a new file, how do you want to determine the
filename?

If you're simply updating 1 or more lines in the source file, you may
want to look at using Tie::File

Could the search string be found more than once in the file? If so,
do you want to change all occurrences or just the first?

For step #1 instead of using @ARGV, I'd either prompt the user for
input or use one of the Getopt modules.
http://search.cpan.org/~jv/Getopt-Lo...Getopt/Long.pm
http://search.cpan.org/~rgarcia/perl.../Getopt/Std.pm
http://search.cpan.org/~rsavage/Geto...topt/Simple.pm

Step #2 is handled with an "or die" statement when creating the
filehandle.

Steps #3 & #4 would be best handled while looping through the source
file line-by-line.
 
Reply With Quote
 
pgodfrin
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 1:12*pm, Ron Bergin <(E-Mail Removed)> wrote:
> On Sep 29, 10:08 am, pgodfrin <(E-Mail Removed)> wrote:
>
>
>
> > I have a need to pass a series of "edits" I'd like to apply in a
> > somewhat controlled manner.

>
> > My pseudo code would be something like:
> > 1. accept as input the file name, old text, new text
> > 2. check existence in file for old text, if not found error out
> > 3. if found, then show before and after text for the whole line
> > 4. Write out file.

>
> > I'm currently using @ARGV for #1 and I intend to slurp the whole file
> > into an array and then use map for #4.

>
> > I'm looking for ideas on a "perlish" way to do #2 and #3. The grep
> > function lets me show before and after like so:

>
> > * * print grep(/$oldtx/,@oldfile);

>
> > But I haven't checked for existence of the $oldtx as of yet. so a type
> > would make this print statement print nothing. I could always use
> > loops and other brute force methods - but it seems like there may be a
> > cooler, perlish way to this... Any ideas?
> > phil

>
> Do you want the output to go to a new file, or simply edit/update the
> source file?
>
> If outputting to a new file, how do you want to determine the
> filename?
>
> If you're simply updating 1 or more lines in the source file, you may
> want to look at using Tie::File
>
> Could the search string be found more than once in the file? *If so,
> do you want to change all occurrences or just the first?
>
> For step #1 instead of using @ARGV, I'd either prompt the user for
> input or use one of the Getopt modules.http://search.cpan.org/~jv/Getopt-Lo...topt/Simple.pm
>
> Step #2 is handled with an "or die" statement when creating the
> filehandle.
>
> Steps #3 & #4 would be best handled while looping through the source
> file line-by-line.


Since these files are relatively small - 30 to 60 lines, I'm ok with
manipulating them in memory. They won't get any larger because the
files are command files that are generated by other unrelated
processes. As such, I could always process them line by line and have
the ultimate control, but I was just looking for some neat features
similar to the map function.

What I want to do is check for the "old text" IN the file not if the
file exists.

Showing before and after snippet is:

print "This will change from:\n";
print grep(/$oldtx/,@oldfile);
print "...to\n";
print grep(s/$newtx/t2ns1/g,@oldfile);

But if the first print grep statement does not find any of the $oldtx
in @oldfile, if the user made a typo for example, then it just prints
nothing. That why I would like to test the existence of the $oldtext.
I suppose:

unless (grep(/$oldtx/,@oldfile)) { die "not found!\n";}

would work. And, since these are very small files, then it would be ok
to do grep multiple times...

pg
 
Reply With Quote
 
Ron Bergin
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 11:37 am, pgodfrin <(E-Mail Removed)> wrote:
> On Sep 29, 1:12 pm, Ron Bergin <(E-Mail Removed)> wrote:
>
>
>
> > On Sep 29, 10:08 am, pgodfrin <(E-Mail Removed)> wrote:

>

[snip]
>
> Since these files are relatively small - 30 to 60 lines, I'm ok with
> manipulating them in memory. They won't get any larger because the
> files are command files that are generated by other unrelated
> processes. As such, I could always process them line by line and have
> the ultimate control, but I was just looking for some neat features
> similar to the map function.
>
> What I want to do is check for the "old text" IN the file not if the
> file exists.
>
> Showing before and after snippet is:
>
> print "This will change from:\n";
> print grep(/$oldtx/,@oldfile);
> print "...to\n";
> print grep(s/$newtx/t2ns1/g,@oldfile);
>
> But if the first print grep statement does not find any of the $oldtx
> in @oldfile, if the user made a typo for example, then it just prints
> nothing. That why I would like to test the existence of the $oldtext.
> I suppose:
>
> unless (grep(/$oldtx/,@oldfile)) { die "not found!\n";}
>
> would work. And, since these are very small files, then it would be ok
> to do grep multiple times...
>
> pg


What's wrong with something like this (untested):

my $found;

open my $filehadle, '<', $file or die "can't open '$file' $!";
while ( <$filehandle> ) {
my $line = $_;

if ( $line =~ s/$oldtx/$newtx/ ) {
$found++;
print "Original:$_";
print "New:$line";
}
}
die "Search pattern was not found\n" unless $found;
 
Reply With Quote
 
Ron Bergin
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 11:37 am, pgodfrin <(E-Mail Removed)> wrote:

[snip]
>
> Showing before and after snippet is:
>
> print "This will change from:\n";
> print grep(/$oldtx/,@oldfile);
> print "...to\n";
> print grep(s/$newtx/t2ns1/g,@oldfile);
>
> But if the first print grep statement does not find any of the $oldtx
> in @oldfile, if the user made a typo for example, then it just prints
> nothing. That why I would like to test the existence of the $oldtext.
> I suppose:
>
> unless (grep(/$oldtx/,@oldfile)) { die "not found!\n";}
>
> would work. And, since these are very small files, then it would be ok
> to do grep multiple times...
>
> pg


Why would you want to intensionally add in inefficiency of the
multiple greps? Granted the files are small and the loss of
efficiency may not be noticed in this case, but to me intensionally
adding inefficiency and possible loss of clarity doesn't make sense.
The loop I showed in my prior comment is clean, efficient and easy to
follow.
 
Reply With Quote
 
pgodfrin
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 2:37*pm, Ron Bergin <(E-Mail Removed)> wrote:
> On Sep 29, 11:37 am, pgodfrin <(E-Mail Removed)> wrote:
>
> [snip]
>
>
>
>
>
> > Showing before and after snippet is:

>
> > print "This will change from:\n";
> > print grep(/$oldtx/,@oldfile);
> > print "...to\n";
> > print grep(s/$newtx/t2ns1/g,@oldfile);

>
> > But if the first print grep statement does not find any of the $oldtx
> > in @oldfile, if the user made a typo for example, then it just prints
> > nothing. That why I would like to test the existence of the $oldtext.
> > I suppose:

>
> > *unless (grep(/$oldtx/,@oldfile)) { die "not found!\n";}

>
> > would work. And, since these are very small files, then it would be ok
> > to do grep multiple times...

>
> > pg

>
> Why would you want to intensionally add in inefficiency of the
> multiple greps? *Granted the files are small and the loss of
> efficiency may not be noticed in this case, but to me intensionally
> adding inefficiency and possible loss of clarity doesn't make sense.
> The loop I showed in my prior comment is clean, efficient and easy to
> follow.


Hi Ron,
Yup your code is good, clean (and fun). I'm just looking for a way to
make the code very, very simple. So, in this case, multiple grep
statements is very, very simple. Albeit not as efficient, but very
simple. In fact I was hoping for something even simpler - where I
could combine the grep and an error check into one line. sort of like:
if(print grep(/$oldtx/,@oldfile)) {print "Text not found\n" and
die;}

But that won't work case printing the result of grep is always
successful.

pg
 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      09-29-2008

Quoth pgodfrin <(E-Mail Removed)>:
> I have a need to pass a series of "edits" I'd like to apply in a
> somewhat controlled manner.
>
> My pseudo code would be something like:
> 1. accept as input the file name, old text, new text
> 2. check existence in file for old text, if not found error out
> 3. if found, then show before and after text for the whole line
> 4. Write out file.
>
> I'm currently using @ARGV for #1 and I intend to slurp the whole file
> into an array and then use map for #4.
>
> I'm looking for ideas on a "perlish" way to do #2 and #3. The grep
> function lets me show before and after like so:
>
> print grep(/$oldtx/,@oldfile);


my @lines = grep /\Q$oldtx/, @oldfile
or die "'$oldtx' not found\n";
print @lines;

--
'Deserve [death]? I daresay he did. Many live that deserve death. And some die
that deserve life. Can you give it to them? Then do not be too eager to deal
out death in judgement. For even the very wise cannot see all ends.'
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Ron Bergin
Guest
Posts: n/a
 
      09-29-2008
On Sep 29, 12:54 pm, pgodfrin <(E-Mail Removed)> wrote:
>
> Hi Ron,
> Yup your code is good, clean (and fun). I'm just looking for a way to
> make the code very, very simple. So, in this case, multiple grep
> statements is very, very simple. Albeit not as efficient, but very
> simple. In fact I was hoping for something even simpler - where I
> could combine the grep and an error check into one line. sort of like:
> if(print grep(/$oldtx/,@oldfile)) {print "Text not found\n" and
> die;}
>
> But that won't work case printing the result of grep is always
> successful.
>

IMO, you seem to have an odd idea of the meaning of simple.

It sounds to me that what you're really after is the most compact code
and not necessarily the simplest.

while ( <$filehandle> ) {
my $line = $_;
# this if statement is 1 line, but probably wrap in the email
if($line =~ s/$oldtx/$newtx/){$found++; print "Original:$_", "New:
$line";}
}
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
perlish way for ( 0 .. $n) , but downcounting hofer Perl Misc 8 08-18-2008 09:29 AM
Perlish dictionary behavior Fred Allen Python 1 06-09-2004 12:18 AM
Perlish dictionary behavior Chris Python 2 06-03-2004 09:08 PM
disappearing of global perlish variables gabriele renzi Python 3 02-20-2004 08:30 AM
Perlish way to get absolute path of current working directory? Bob Walton Perl Misc 9 09-26-2003 01:48 PM



Advertisments