• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1104
  • Last Modified:

add/delete line in file with perl

Let say I have a file named abc.txt. And I would like to delete a line with the sentence "Pls delete this line" in the file and add a new line with "deleted successfully" at the end of the file. How to I do it in perl? Pls give advice to me.
0
abc88
Asked:
abc88
  • 3
  • 2
  • 2
  • +1
1 Solution
 
PaulmulCommented:
open (INFILE, ">abc.txt") || die "Can not open for reading: $!";

while ($line = <INFILE>) {  
               
             
        $position  = index($line,$search);

        if ($line == "Pls delete this line" ) {
     
     $line = "deleted succesfully";

     }    


close(INFILE);

#########################################

Something to that effect any way.

Paul
0
 
PaulmulCommented:
I wrote this to search a cd archive. Similar principle to what you asked.

##########################################

 open (INFILE, "archive.txt") || die "Can not open for reading: $!";

 print("Enter the file name to search for\n");
     
 $search = <STDIN>;

 $search =~ s/\n//g;                #cut off end space

 $search = uc($search);

 print ("\n");                    #space after input

 
    $i = 0;

    while ($line = <INFILE>) {  
               
                     
     
        $position  = index($line,$search);

        if ($position > -1) {
                   
     @result[$i]= $line;
        $i++;
     
          }

     }
     
     print (@result);
         

close(INFILE);
0
 
ItatsumakiCommented:
Personally I'd prefer to do it this way, but the above solutions are close to working for you, I think:

# Locals
my $deleted_flag = 0;

# File-handling
open(IN,  "<$infile");
open(OUT, ">temp0001.txt");

# File-processing
while (<IN>) {
    chomp();
    if (/Pls delete this line/) {
       $deleted_flag = 1;
       next();
       }
    else {
       print OUT;
       }
    }

# Summary line
if ($deleted_flag) {
     print OUT "Line was successfully deleted\n";
     }

# File-handling
close(IN);
close(OUT);
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
PaulmulCommented:
That uses an out file which is unnecessary and a waste of system resources. If the line simply needs to be replaced there would still be the old file.

Paul
0
 
ItatsumakiCommented:
Indeed, but to do that requires him to be able to lock the old file, which may or may not be possible.

This way he could add code like:

while (1) {
    if (!flock($infile, 2)) {
        sleep 15;
        }
    else {
        unlink($infile);
        rename($outfile, $infile);
        last();
        }
    }

So it's just safer, but less efficient.
Also if multiple matches are needed, he'll have to add a while-loop around the index() call.
 
0
 
wilcoxonCommented:
And another option:

use Fcntl qw(O_RDWR O_EXLOCK)
use Tie::File;

# tie the array @lines to the file abc.txt
# open for read/write and with an exclusive lock
# remove O_EXLOCK if you don't want or can't get an exclusive lock
tie @lines, 'Tie::File', 'abc.txt', mode => O_RDWR|O_EXLOCK;

# option 1 - not entirely sure grep works with a tied file
my $old_cnt = scalar @lines;
@lines = grep { !/Pls delete this line/ };
push @lines, "deleted successfully" unless ($old_cnt == scalar @lines);

# option 2
# now @lines is the file abc.txt
# could use grep instead of first or skip this check altogether
use List::Utils qw(first);
exit unless first /Pls delete this line/ @lines;
my $del = 0;
for my $i (0..@lines-1) {
    splice(lines, $i, 1), $del++ if ($lines[$i] =~ /Pls delete this line/);
}
push @lines, 'deleted successfully' if $del;
0
 
abc88Author Commented:
Hi Wilcoxon,

I downloaded Fcntl.pm, Tie/File.pm, XSLoader.pm and DynaLoader.pm from internet and located it in /pgfs5/eng/ayeoh2/pl/pm
 and I tried:

use lib "/pgfs5/eng/ayeoh2/pl/pm";
use Fcntl qw(O_RDWR O_EXLOCK);
use Tie::File;

tie @lines, 'Tie::File', 'abc.txt', mode => O_RDWR|O_EXLOCK;

my $old_cnt = scalar @lines;
@lines = grep { !/Pls delete this line/ };
push @lines, "deleted successfully" unless ($old_cnt == scalar @lines);

The errors below prompted out:

Can't declare undef operator in my at /pgfs5/eng/ayeoh2/pl/pm/Fcntl.pm line 207, near ") ="
BEGIN failed--compilation aborted at try.pl line 4.

I am not familiar with these perl module. Pls advice.

0
 
abc88Author Commented:
I then comment out line:

 my (undef,$file,$line) = caller; <line 207 in Fcntl.pm>

and replace:

  (undef,$file,$line) = caller;

it show me the error:

&Fcntl::constant not defined at /pgfs5/eng/ayeoh2/pl/pm/Fcntl.pm line 204.
BEGIN failed--compilation aborted at try.pl line 4.
0
 
wilcoxonCommented:
I'm not sure what the problem is unless there is a version mismatch.  You should not have needed to download most of those.

Fcntl, XSLoader, and DynaLoader are part of the perl core dating back at least to 5.004 (the earliest I can check on www.perldoc.com).

Tie::File was made part of the core in 5.8.

Try deleting the modules that you put under /pgfs5/eng/ayeoh2/pl/pm (except Tie::File unless you are using perl 5.8).

If you have a perl older than 5.005, I would strongly encourage you to upgrade.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 3
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now