How do I swap using a single s/// all occurrences of two substrings?
How do I write a regex to replace a
with b
and b
with a
so that a&b
will become b&a
?
UPDATE
It should replace all 开发者_如何学Gooccurrences of a
with b
and each b
with a
. The a&b
is just an example to illustrate what I want. Sorry for the confusion.
You can use capturing groups and positional replacements to do this:
pax$ echo 'a&b' | perl -pne 's/([^&]*)&(.*)/\2&\1/'
b&a
The (blah blah)
bits capture the "blah blah" and save it in a register for later use in the replacement string. When used with a replacement section like \1
, the captured text is placed in the result.
So that regex simply captures all non-ampersand characters into register 1, the an ampersand then all the rest of the string into register 2.
In the substitution, it gives you register 2, an ampersand, then register 1.
If, as you mention in a comment, you want to do &
and |
, you need to capture and use the operator as well:
pax$ echo 'a&b' | perl -pne 's/([^&|]*)([&|])(.*)/\3\2\1/'
b&a
pax$ echo 'a|b' | perl -pne 's/([^&|]*)([&|])(.*)/\3\2\1/'
b|a
You can see that the positional replacements are slightly different now since you're capturing more groups but the concept is still identical.
The traditional generic way is:
my $string = "abcdefedcba";
my %subst = ( 'a' => 'b', 'b' => 'a' );
$string =~ s/(@{[ join '|', map quotemeta, sort { length($b) <=> length($a) } keys %subst ]})/$subst{$1}/g;
print $string;
Non-generically:
$string =~ s/(a|b)/{a=>'b',b=>'a'}->{$1}/ge;
Per your updated instructions:
$str =~ tr/ab/ba/;
Another possibility is to do 3 s///
.
$_ = 'a&b'
# First, change every 'a' to something that does not appear in your string
s/a/\0/g;
# Then, change 'b' to 'a'
s/b/a/g;
# And now change your special character to b
s/\0/b/g;
I'd like to suggest a variation of this answer. Beginner Regex: Multiple Replaces
$text =~ s/(cat|tomatoes)/ ${{ qw<tomatoes cat cat tomatoes> }}{$1} /ge;
精彩评论