Search code examples
perlsplice

Perl how to introduce a text in front of a keyword(match) and keep the rest from a file


I am new to perl and I need to edit a text file by adding some text after i find a keyword(match), I need to save the changes in the same file but keeping all the old information, not overwrite anything.

The keyword (match) and the information I want to add will remain the same everytime even if the other data from the file will change.

To make a summary:

data that will change (not interested)

...

empty spaces < DATA >B506JGHD (< DATA > it would be the keyword(match) and i want to add for example 00000001 after it)

output that I need:empty spaces< DATA >00000001B506JGHD

...

empty spaces< DATA >J6443MNF

output:empty spaces< DATA >00000002J6443MNF

...


empty spaces< DATA >C89583F

output:empty spaces< DATA >00000003C89583F

...
other data (not interested)  

and so on, it would be like 7 < DATA > in the file so I want to add 00000000 to 00000006 for each < DATA >.

I am looking for a simple solution if exists, I know that I probably need to read and go trough the text file find the keyword and rewrite everything but I am not sure how to do this.

What I tried so far is this:

use strict;
use warnings;

open FILE, "<FL_85E920795_Y060_H21_V001_E.odx" or die $!;
my @lines = < FILE >;
close FILE or die $!;

my $idx = 0;
my $string = '00000000';
do {
    if($lines[$idx] =~ /< DATA >/) 
        {
            splice @lines, $idx, 0, $string++;
            $idx++;
        }
    $idx++;
    } until($idx >= @lines);

open FILE, ">FL_85E920795_Y060_H21_V001_E.odx" or die $!;
print FILE join("",@lines);
close FILE;

but does not help me so much as my output is like this: 00000000 empty spaces < DATA >Info, if I try to move the data that I want in front of < DATA > it overwrites everything.

The first response that will work for me I will accept as a solution. Thank you very much


Solution

  • #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my $counter = "00000000";
    while (<>) {
       s{< DATA >\K}{ $counter++ }eg;
       print;
    }
    

    Usage:

    fn=FL_85E920795_Y060_H21_V001_E.odx
    the_script "$fn" >"$fn".new
    mv "$fn".new "$fn"
    

    \K "keeps" what was matched up to the \K, and thus replaces only the empty string that follows < DATA > with the value returned by the replacement expression.


    As a "one-liner":

    perl -i -pe'BEGIN { $c = "00000000" }  s{< DATA >\K}{ $c++ }eg' \
       FL_85E920795_Y060_H21_V001_E.odx