Limit the translation to just one word in a phrase?

Viewed 95

Coming new to Perl world from Python, and wonder if there is a simple way to limit the translation or replace to just one word in a phrase?

In the example, the 2nd word kind also got changed to lind. Is there a simple way to do the translation without diving into some looping? Thanks.

The first word has been correctly translated to gazelle, but 2nd word has been changed too as you can see.


my $string = 'gazekke is one kind of antelope';

my $count = ($string =~ tr/k/l/);

print "There are $count changes \n";

print $string;         # gazelle is one lind of antelope    <-- kind becomes lind too!
3 Answers

I don't know of an option for tr to stop translation after the first word. But you can use a regex with backreferences for this.

use strict;

my $string = 'gazekke is one kind of antelope';

# Match first word in $1 and rest of sentence in $2.
$string =~ m/(\w+)(.*)/;

# Translate all k's to l's in the first word.
(my $translated = $1) =~ tr/k/l/;

# Concatenate the translated first word with the rest
$string = "$translated$2";

print $string;

Outputs: gazelle is one kind of antelope

Pick the first match (a word in this case), precisely what regex does when without /g, and in that word replace all wanted characters, by running code in the replacement side, by /e

$string =~ s{(\w+)}{ $1 =~ s/k/l/gr }e;

In the regex in the replacement side, /r modifier makes it handily return the changed string and doesn't change the original, what also allows a substitution to run on $1 (which can't be modified as is a read-only).

tr is a character class transliterator. For anything else you would use regex.

$string =~ s/gazekke/gazelle/;

You can put a code block as the second half of s/// to do more complicated replacements or transmogrifications.

$string =~ s{([A-Za-z]+)}{ &mangler($1) if $should_be_mangled{$1}; }ge;

Edit: Here's how you would first locate a phrase and then work on it.

$phrase_regex = qr/(?|(gazekke) is one kind of antelope|(etc))/;
$string =~ s{($phrase_regex)}{
  my $match = $1;
  my $word = $2;
  $match =~ s{$word}{
    my $new = $new_word_map{$word};
    &additional_mangling($new);
    $new;
  }e;
  $match;
}ge;


Here's the Perl regex documentation. https://perldoc.perl.org/perlre

Related