Aditya J.
Aditya J.

Reputation: 131

Perl: Number every instance of a word in a text file

I need to edit a text file that is formatted something like:

> Word text text text text
Text
Text
> Word text text text text
Text
Text

And make it look like:

>Word1 text text text text
Text
Text
>Word2 text text text text
Text
Text

Basically, I need to modify every instance of the string " Word" and turn it into "Word" followed by a number corresponding to the number of instances the string has appeared in the text file so far. I'm new to perl and have no idea what I'm doing. Here's what I have:

$file = "test.txt";

my %count;
my $word = " Word";

#Open and read data
open (FILE, "<$file") or die "Cannot open $file: $!\n";
@lines= <FILE>;
foreach my $word{
    my $count++;
}
close FILE;

my $counter = my $count + 1;
my $curr_ct = my $counter - my $count;

#Open same file for editing now
open (STDOUT, ">$file") or die "Cannot open $file: $!\n";


while (my $count > 0){
    s/ Word/Word$curr_ct/
    my $count--;
    my $curr_ct = my $counter - my $count;
    print;
}

close STDOUT;

Upvotes: 0

Views: 80

Answers (2)

ikegami
ikegami

Reputation: 385839

There's no reason to use (?{ }). When you use /e, the substitution expression is evaluated as Perl code for every match. That's all you need here.

#!/usr/bin/perl

use strict;
use warnings;

my $word = 'Word';

my $count;
while (<>) {
    s/\b\Q$word\E\b/ $word . ++$count /eg;
    print;
}

5.10 introduced \K which can make the key line even shorter!

s/\b\Q$word\E\b\K/ ++$count /eg;

Other improvements:

  • The \b make it so sword or wordy aren't matched.
  • The \Q..\E make it so $word can safely contain non-word characters.

Upvotes: 5

stevieb
stevieb

Reputation: 9296

You could use a zero-width code evaluation expression assertion, eg: (?{...}) within the regex to increase the count value on each match, then use that count in the substitution side:

Note that code eval expressions are considered experimental, according to the docs.

use warnings;
use strict;

my $word = 'Word';
my $file = 'file.txt';

open my $fh, '<', $file or die $!;

my $count;

while (<$fh>){
    s/$word(?{$count++})/$word$count/g;
    print;
}

Input:

> Word text text text text
Text
Text
> Word text text text text
Text
Text

Output:

> Word1 text text text text
Text
Text
> Word2 text text text text
Text
Text

Upvotes: -1

Related Questions