#!/usr/bin/perl -w use strict; use warnings; my $S = 'ABC ABC CBA ACB CAB BAC CAB CAB CARAB CACBA AXCK'; $S = Replace($S, ' A', '-@'); print "\n$S"; exit; ################################################## # v2019.12.6 # This function scans string S and replaces the # first N occurrences of string A with string B # and returns a new string. If N is -1 then only # the last instance is replaced. # Usage: STRING = Replace(STRING_S, STRING_A, [STRING_B, [N]]) # sub Replace { # First, we make sure that required arguments are available # and any special scenarios are handled correctly. defined $_[0] or return ''; defined $_[1] or return $_[0]; my $B = defined $_[2] ? $_[2] : ''; my $N = defined $_[3] ? $_[3] : 0x7FFFFFFF; my ($LA, $LB) = (length($_[1]), length($B)); ($N && $LA && $LA <= length($_[0])) or return $_[0]; my ($LAST, $F, $X) = (0, 0, $_[0]); if ($N > 0x7FFFFFFE) { # If we get here, it means that N was omitted and # so there's no restriction on how many times we # have to replace. We just replace all of them, # and it doesn't matter if we replace from right # to left or from left to right. my $A = $_[1]; # $X =~ s/\Q$A\E/\Q$B\E/g; # THIS IS NOT RIGHT $X =~ s/\Q$A\E/$B/g; # THIS IS CORRECT. # thank you, Corion. } elsif ($N < 0) { # If we get here, we must not replace every # instance, and we must search from right to left. $F = length($X); while (($F = rindex($X, $_[1], $F)) >= 0) { substr($X, $F, $LA) = $B; ++$N or last; } } elsif ($LA == $LB) { # If we get here, we must replace only N number # of instances, and the output string will be the # same length as the input string. # (Search from left to right.) while (($F = index($X, $_[1], $F)) >= 0) { substr($X, $F, $LA) = $B; $F += $LB; --$N or last; } } else { # In this case, output string will NOT be the # same length as the input string. # We must replace only N number of instances, # and we go from left to right. $X = ''; while (($F = index($_[0], $_[1], $F)) >= 0) { $X .= substr($_[0], $LAST, $F - $LAST); $X .= $B; $F += $LA; $LAST = $F; --$N or last; } $X .= substr($_[0], $LAST); } return $X; }