Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

deleting lines from file

by Anonymous Monk
on Mar 18, 2004 at 02:27 UTC ( [id://337586]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks , I have this silly issue and need your help. I am opening a file then deleting a line from it based on the user input.
oldfile ------- one 111 ury two 222 sld th ese ll my $valueToDelete = "two 222 sld"; open my $fh, "oldfile" or die "open failed: $!"; my $line; while ($line = <$fh>) { chomp $line; $dataFileContains{$line}++; } close $fh; open my $ff, "newfile" or die "open failed: $!"; my $line2; while ($line2 = <$ff>) { chomp $line2; print $dataFileContains{$line2} unless ($dataFileContains{$line2} eq $ +valueToDelete); } close $ff;

Replies are listed 'Best First'.
Re: deleting lines from file
by jweed (Chaplain) on Mar 18, 2004 at 02:51 UTC
    It's unclear what "newfile" should contain. If you want it to have
    one 111 ury
    th  ese  ll
    
    in it, thenyour program makes absolutely no sense. Since this smells like homework, here are some questions I am asking myself, and then a proposed solution that the prof probably won't accept ;) :
    1. Why are you counting occurances or existance of the lines in oldfile? How does this advance your aims to delete a line?
    2. Why are you printing the number of times oldfile has a certain line to the standard output. This makes little sense to me.
    And, to wrap it up, a solution for inplace editing (this is as per what you seem to be asking.):
    #!/usr/bin/perl use strict; use warnings; use Tie::File; my $value_to_delete = <STDIN>; chomp $value_to_delete; tie my @file, 'Tie::File', "file" or die "Couldn't open: $!"; @file = grep { $_ ne $value_to_delete } @file; untie @file;
    N.B. This solution is quite cost effective memory-wise, because Tie::File does some cool behind-the-scenes stuff so you don't have to read everything in at once. This is huge if the file is very large.

    UPDATE: Here's a non-in place solution:
    #!/usr/bin/perl -pi.orig BEGIN {$value_to_delete = <STDIN>} undef $_ if $_ eq $value_to_delete;



    Code is (almost) always untested.
    http://www.justicepoetic.net/
Re: deleting lines from file
by pbeckingham (Parson) on Mar 18, 2004 at 03:00 UTC

    Or the file could be read and written in one action, and the deletion can be handled by a simple substitution.

    #! /usr/bin/perl -w use strict; my $valueToDelete = "two 222 sld"; my $content = ''; open my $fh, 'oldfile' || die $!; do {local $/; $content = <$fh>}; close $fh; $content =~ s/^$valueToDelete\n//m; open $fh, '>newfile' || die $!; print $fh $content; close $fh;

      Yup, I like that one better than my array solution.
Re: deleting lines from file
by phenom (Chaplain) on Mar 18, 2004 at 02:42 UTC
    Not tested, but how about:
    #!/usr/bin/perl use strict; use warnings; my $valueToDelete = $ARGV[0] || "two 222 sld"; open(FH, "oldfile") or die "open failed: $!"; my @contents = <FH>; close(FH); open(FH, ">oldfile") or die "open failed: $!"; foreach my $line (@contents) { print FH $line if($line !~ /$valueToDelete/); } close(FH);
Re: deleting lines from file
by graff (Chancellor) on Mar 18, 2004 at 05:27 UTC
    You're right about this being silly. This is what the unix "grep" command is for (and grep is available for ms-windows):
    grep -v "two 222 sld" oldfile > newfile
    Or, to do that with "pure Perl" on the command line:
    perl -ne "print unless /two 222 sld/" oldfile > newfile
    Now, if your talking about handling user input (to specify the line(s) to be deleted) that involves more than simple string matches, or weird stuff like unicode characters, then that's more interesting, but most cases are still one-liner command-line level jobs -- the kind of stuff that people used to do with the unix "awk" program (also available for ms-windows), which has been pretty much fully absorbed and replaced by perl. E.g. if the user wants to eliminate lines where the second token is an even number:
    perl -ane 'print unless( $F[1]=~/^(\d+)$/ and $1 % 2 == 0 )'
    (In this case, users of unix-style shells will want to use single quotes around the script to keep the shell from treating "$F" and "$1" as shell variables, whereas "MS-DOS Prompt" users will probably prefer double-quotes.)
Re: deleting lines from file
by AcidHawk (Vicar) on Mar 18, 2004 at 12:30 UTC
    Just a few comments (I know it's a little late but hopefully adds more clarity).

    Firstly, once you read in a line from oldfile you need to keep it somewhere to check it against $valueToDelete. There are many ways to do this. These include putting each line into an array or even a hash etc.

    Secondly, does newfile have anything in it..? if you are appending to newfile your open should look like

    open my $ff, ">>newfile" or die "open failed: $!\n";
    or if you are creating newfile from scratch, your open should look like
    open my $ff, ">newfile" or die "open failed: $!\n";
    Also if you are creating the file there will be nothing in it to read so you don't need to do the while loop or the chomp. You can simply do the print if the value you want to print is not like the $valueToDelete. Should you choose to put the lines from oldfile into an array your code would look something like
    foreach my $line (@oldlines) { unless ($line eq $valueToDelete) { print $ff "$line\n"; } }
    Another quick note is that when you are printing to newfile you must use your filehandle $ff.
    -----
    Of all the things I've lost in my life, its my mind I miss the most.
Re: deleting lines from file
by Anonymous Monk on Mar 18, 2004 at 03:57 UTC
Re: deleting lines from file
by etcshadow (Priest) on Mar 18, 2004 at 02:35 UTC
    Where's the question?
    ------------ :Wq Not an editor command: Wq

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://337586]
Approved by jweed
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (7)
As of 2024-03-28 08:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found