CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
substitution question

 



joseph4325
Novice

Jun 10, 2013, 4:06 PM

Post #1 of 8 (755 views)
substitution question Can't Post

I'm hoping someone can just help me clean up this script. The goal of it is to scan a file whose contents would be like:
(string),0
(string),1

If the string exists in the file, and has a $count=0, it does a find/replace on that line changing it from "(string),0" to (string),1". If $count > 0 it does the opposite change.

If the string does not exist in the file, it appends a new line writing 0 or 1 based on the count.

The following code does exactly what i need it to, but it seems like there's probably a better way to do it than what i'm doing. Was hoping someone could help me clean it up some.


Code
 
my $filename ='C:\test.txt';

open(FILE, "<$filename") || die "File not found";
my @lines = <FILE>;
close(FILE);

open(FILE, "$filename") or die "Cant open $filename\n";
local $/ = undef;
my $line = <FILE>;
close(FILE);

open(FILE, ">$filename") || die "File not found";

open(my $fh, '>>', $filename);

my @newlines;

my $count = 0;
my $sub = '$string';

if ($count == 0){
foreach(@lines){
$_ =~ s/$sub,0/$sub,1/g;
push(@newlines,$_);
print FILE @newlines;
}
}

else{

foreach(@lines){
$_ =~ s/$sub,1/$sub,0/g;
push(@newlines,$_);
print FILE @newlines;
}
}

if ($line !~ /$sub/ && $count ==0){
print $fh "$sub,1\n";
}

elsif($line !~ /$cname/ && $count > 0){
print $fh "$sub,0\n";
}

close(FILE);
close $fh;



hwnd
User

Jun 10, 2013, 5:44 PM

Post #2 of 8 (740 views)
Re: [joseph4325] substitution question [In reply to] Can't Post

You could do something like this:


Code
my @data;  

open my $fh, '<', 'file.txt' or die "failed: $!";
open my $out, '>', 'output.txt' or die "failed: $!";

while (<$fh>) {
my ($str, $cnt) = split /\,/;
$cnt == 0 ? $cnt = 1 :
$cnt > 0 ? $cnt = 0 : 0;
push @data, "$str,$cnt";
}

print $out "$_\n" for @data;

close $fh;
close $out;



Laurent_R
Veteran / Moderator

Jun 10, 2013, 11:43 PM

Post #3 of 8 (733 views)
Re: [joseph4325] substitution question [In reply to] Can't Post

A good solution has been given to you, just a couple iof comments on your code.

Why are you opening $filename four times where you really need to open once the input file and once the output file?

If you don't need to have your file entirely loaded in memory (and you probably don't need in this case), don't do it, just ioterate over it (read line by line). It will not blow at your face if or when the file grows much larger. And in the case where you really need to have it in memory, just do it once, not twice.

This:


Code
my $count = 0;  
my $sub = '$string';

if ($count == 0){ #...


is quite useless, $count is bound to be 0.

Final point: I don't think your code is really doing what your are describing, but it may be the code that is wrong, or maybe your code is right and your description wrong.


FishMonger
Veteran / Moderator

Jun 11, 2013, 8:22 AM

Post #4 of 8 (725 views)
Re: [hwnd] substitution question [In reply to] Can't Post


Quote

Code
  $cnt == 0 ? $cnt = 1 :  
$cnt > 0 ? $cnt = 0 : 0;



Is better written as:

Code
$cnt = $cnt == 0 ? 1 : 0;


Another option:

Code
my %swap = ( 0=>1, 1=>0); 

while (my $line = <$fh>) {
chomp $line;
my ($string, $cnt) = split /,/, $line;
push @data, "$string,$swap{$cnt}";
}



BillKSmith
Veteran

Jun 11, 2013, 10:10 AM

Post #5 of 8 (719 views)
Re: [joseph4325] substitution question [In reply to] Can't Post

A very different approach. (My FORTRAN is showing)

Code
use strict; 
use warnings;
foreach my $line (<DATA>) {
chomp $line;
$line =~ s/([01])\s*$/1-$1/e;
print $line, "\n";
}
__DATA__
(string),0
(string),1
1
0
this is a string,1


UPDATE: Removed unnecessary code.
Good Luck,
Bill

(This post was edited by BillKSmith on Jun 11, 2013, 10:12 AM)


joseph4325
Novice

Jun 11, 2013, 12:13 PM

Post #6 of 8 (711 views)
Re: [Laurent_R] substitution question [In reply to] Can't Post


Quote
Why are you opening $filename four times where you really need to open once the input file and once the output file?


This is what i'm trying to fix. My problem is in 1 condition i need it to overwrite an existing line, in a separate condition i need to append to the file, and in the 3rd i'm reading from the file. So do i need at least 2 or is there some way i can append and overwrite in the same file open? Also i'm having problem combining my 2 uses of the file open in read mode to just one.


FishMonger
Veteran / Moderator

Jun 11, 2013, 2:15 PM

Post #7 of 8 (702 views)
Re: [joseph4325] substitution question [In reply to] Can't Post

Don't open the file multiple times. Use the Tie::File module and access the file as an array which can be easily updated.

http://search.cpan.org/~toddr/Tie-File-0.98/lib/Tie/File.pm


2teez
Novice

Jun 11, 2013, 11:59 PM

Post #8 of 8 (687 views)
Re: [joseph4325] substitution question [In reply to] Can't Post


Quote
Why are you opening $filename four times where you really need to open once the input file and once the output file?

Good question to ask...

Quote
This is what i'm trying to fix. My problem is in 1 condition i need it to overwrite an existing line, in a separate condition i need to append to the file, and in the 3rd i'm reading from the file

Under which condition are you doing the in place editing? And under which are you writing out?

Quote
or is there some way i can append and overwrite in the same file open?

FishMonger has given you one way to do it. You can as well use '-i' on the CLI or '$^I' from your script to do in-place editing. Please see http://perldoc.perl.org/perlrun.html#Command-Switches.
Moreover, the code below could also help.

Code
use warnings; 
use strict;

my $filename = 'test.txt';

open my $fh2, '>', 'output.txt' or die "can't open file: $!";
open my $fh, '<', $filename or die "can't open file: $!";

while (<$fh>) {
chomp;
if (/(.+?)(-?\d+?)$/) {
print $fh2 $2 <= 0 ? qq[$1 1 $/] : qq[$1 0 $/];
}
elsif (/(-?\d+?)$/) {
print $fh2 $1 <= 0 ? qq[string, 1$/] : qq[string, 0$/];
}
}

close $fh or die $!;
close $fh2 or die $!;



(This post was edited by 2teez on Jun 12, 2013, 12:20 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives