#!/usr/bin/perl -w use strict; my $data_stg = 'junk text update 8923 mark complete update 8324 mark ' . 'complete more junk update 5438 and 5843 and 1522 mark ' . 'complete update 8435 and 9323 mark complete true junk'; pos( $data_stg ) = 0; my %mult_updates; my $pass = 1; while ( $data_stg =~ /(update \d+( and \d+)+ mark complete)/ig ) { my $mult_update_pos = pos( $data_stg ); print "$pass pos: '$mult_update_pos'\n"; my $mult_update = $1; print "$pass orig_mult_update: '$mult_update'\n"; my $mult_update_length = length $mult_update; print "$pass length: '$mult_update_length'\n"; $mult_update =~ s/and (\d+)/mark complete update $1/gi; print "$pass new_mult_update: '$mult_update'\n"; $mult_updates{ $mult_update_pos - $mult_update_length } = [ ($mult_update_length, $mult_update) ]; } continue { $pass++; } # Work backwards from the end of the string, doing substr # on positions which have been identified as having code to # replace. Let the key define a starting position and the # key's value contain an array ref describing the length # of the target and the desired replacement text. foreach ( sort {$b <=> $a} keys %mult_updates ) { substr( $data_stg, $_, $mult_updates{$_}->[0], $mult_updates{$_}->[1] ); } print "\n$data_stg\n";