Swapping letters with regexp

How can I swap the letter o with the letter e and e with o?

I just tried this but I don't think this is a good way of doing this. Is there a better way?

my $str  = 'Absolute force';
$str =~ s/e/___eee___/g;
$str =~ s/o/e/g;
$str =~ s/___eee___/o/g;

Output: Abseluto ferco

Answers


Use the transliteration operator:

$str =~ y/oe/eo/;

E.g.

$ echo "Absolute force" | perl -pe 'y/oe/eo/'
Abseluto ferco

As has already been said, the way to do this is the transliteration operator

tr/SEARCHLIST/REPLACEMENTLIST/cdsr

y/SEARCHLIST/REPLACEMENTLIST/cdsr

Transliterates all occurrences of the characters found in the search list with the corresponding character in the replacement list. It returns the number of characters replaced or deleted. If no string is specified via the =~ or !~ operator, the $_ string is transliterated.

However, I want to commend you on your creative use of regular expressions. Your solution works, although the placeholder string _ee_ would've been sufficient.

tr is only going to help you for character replacements though, so I'd like to quickly teach you how to utilize regular expressions for a more complicated mass replacement. Basically, you just use the /e tag to execute code in the RHS. The following will also do the replacement you were aiming for:

my $str  = 'Absolute force';

$str =~ s/([eo])/$1 eq 'e' ? 'o' : 'e'/eg;

print $str;

Outputs:

Abseluto ferco

Note how the LHS (left hand side) matches both o and e, and them the RHS (right hand side) does a test to see which matched and returns the opposite for replacement.

Now, it's common to have a list of words that you want to replace, so it's convenient to just build a hash of your from/to values and then dynamically build the regular expression. The following does that:

my $str  = 'Hello, foo. How about baz? Never forget bar.';

my %words = (
    foo  => 'bar',
    bar  => 'baz',
    baz  => 'foo',
);
my $wordlist_re = '(?:' . join('|', map quotemeta, keys %words) . ')';

$str =~ s/\b($wordlist_re)\b/$words{$1}/eg;

Outputs:

Hello, bar. How about foo? Never forget baz.

This above could've worked for your e and o case, as well, but would've been overkill. Note how I use quotemeta to escape the keys in case they contained a regular expression special character. I also intentionally used a non-capturing group around them in $wordlist_re so that variable could be dropped into any regex and behave as desired. I then put the capturing group inside the s/// because it's important to be able to see what's being captured in a regex without having to backtrack to the value of an interpolated variable.


The tr/// operator is best. However, if you wanted to use the s/// operator (to handle more than just single letter substitutions), you could write

$ echo 'Absolute force' | perl -pe 's/(e)|o/$1 ? "o" : "e"/eg'
Abseluto ferco

The capturing parentheses avoid the redundant $1 eq 'e' test in @Miller's answer.


from man sed:

y/source/dest/ Transliterate the characters in the pattern space which appear in source to the corresponding character in dest.

and tr command can do this too:

$ echo "Absolute force" | tr 'oe' 'eo'
Abseluto ferco

Need Your Help

Using WebSocket on Apache server

php html5 apache websocket phpwebsocket

With all the buzz around WebSockets, it's pretty hard to find a good walkthrough on how to use them with an Apache server on Google.