4

In a text file, I'd like to insert a NEW line of text before each and every match of another line of text, using perl.

Example - my file is:

holiday
april
icecream: sunday
jujubee
carefree
icecream: sunday
Christmas
icecream: sunday
towel

...

I would like to insert a line of text 'icecream: saturday' BEFORE the 'icecream: sunday' lines. So afterwards, the text file would look like. Yes, I DO need the colon : in both the searched and replaced pattern.

holiday
april
icecream: saturday
icecream: sunday
jujubee
carefree
icecream: saturday
icecream: sunday
Christmas
icecream: saturday
icecream: sunday
towel
...

I'd like to do this using perl 5.14 on a Windows PC. I've already got Perl installed. I have searched and tried many of the other examples here on this website but they aren't working for me, and unfortunately I am not a complete expert of Perl.

I've got Cygwin sed also if there is an example to use sed too.

durron597
  • 31,968
  • 17
  • 99
  • 158
user1864091
  • 41
  • 1
  • 2

3 Answers3

8

This is a command-line version.

perl -i.bak -pe '$_ = qq[icecream: saturday\n$_] if $_ eq qq[icecream: sunday\n]' yourfile.txt

Explanation of command line options:

-i.bak : Act on the input file, creating a backup version with the extension .bak

-p : Loop through each line of the input file putting the line into $_ and print $_ after each iteration

-e : Execute this code for each line in the input file

Perl's command line options are documented in perlrun.

Explanation of code:

If the line of data (in $_) is "icecream: sunday\n", then prepend "icecream: saturday\n" to the line.

Then just print $_ (which is done implicitly with the -p flag).

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
2
open FILE, "<icecream.txt" or die $!;
my @lines = <FILE>;
close FILE or die $!;

my $idx = 0;
do {
    if($lines[$idx] =~ /icecream: sunday/) {
        splice @lines, $idx, 0, "icecream: saturday\n";
        $idx++;
    }
    $idx++;
} until($idx >= @lines);

open FILE, ">icecream.txt" or die $!;
print FILE join("",@lines);
close FILE;
David
  • 6,462
  • 2
  • 25
  • 22
  • Hi thank you.
    Unfortunately that did not seem to work. I received the message, "Can't locate IO/All.pm in @INC (@INC contains: C:/Perl64/site/lib C:/Perl64/lib .) at callpl.pl line 1. BEGIN failed--compilation aborted at callpl.pl line 1."
    – user1864091 Nov 29 '12 at 19:01
  • @user1864091 You need to install the IO::All module from CPAN. You should be able to do this by running `perl -MCPAN -e "install IO::All"` from the command line, or by using the Perl Package Manager utility if you're using Active State perl. – David Nov 29 '12 at 19:11
  • @user1864091 Updated the script and removed the requirement to use any perl modules. – David Nov 29 '12 at 19:19
  • Thanks David, removal of the perl modules in your update script worked perfectly. Great job. – user1864091 Nov 29 '12 at 20:11
  • @user1864091 Thanks! Glad it worked out. Please mark my solution as answered when you have a moment. – David Nov 29 '12 at 20:21
2

Here's an option using the File::Slurp Module:

use strict;
use warnings;
use File::Slurp qw/:edit/;

edit_file sub { s/(icecream: sunday)/icecream: saturday\n$1/g }, 'data.txt';

And an option not using that Module:

use strict;
use warnings;

open my $fhIn,  '<', 'data.txt'          or die $!;
open my $fhOut, '>', 'data_modified.txt' or die $!;

while (<$fhIn>) {
    print $fhOut "icecream: saturday\n" if /icecream: sunday/;
    print $fhOut $_;
}

close $fhOut;
close $fhIn;
Kenosis
  • 6,196
  • 1
  • 16
  • 16