Ответ 1
Используйте оператор транслитерации:
$str =~ y/oe/eo/;
например.
$ echo "Absolute force" | perl -pe 'y/oe/eo/'
Abseluto ferco
Как я могу поменять букву o
буквой e
и e
на o
?
Я просто попробовал это, но я не думаю, что это хороший способ сделать это. Есть ли лучший способ?
my $str = 'Absolute force';
$str =~ s/e/___eee___/g;
$str =~ s/o/e/g;
$str =~ s/___eee___/o/g;
Выход: Abseluto ferco
Используйте оператор транслитерации:
$str =~ y/oe/eo/;
например.
$ echo "Absolute force" | perl -pe 'y/oe/eo/'
Abseluto ferco
Как уже было сказано, способ сделать это - transliteration operator
tr/SEARCHLIST/REPLACEMENTLIST/cdsr
y/SEARCHLIST/REPLACEMENTLIST/cdsr
Транслитерирует все вхождения символов, найденных в списке поиска, с соответствующим символом в списке замещения. Он возвращает количество замененных или удаленных символов. Если строка не указана с помощью оператора
=~
или!~
, строка$_
транслитерируется.
Однако я хочу поблагодарить вас за ваше творческое использование регулярных выражений. Ваше решение работает, хотя строка-заполнитель _ee_
была бы достаточной.
tr
только поможет вам в замене персонажа, поэтому я хотел бы научить вас, как использовать регулярные выражения для более сложной массовой замены. В принципе, вы просто используете тег /e
для выполнения кода в RHS. Следующее также сделает замену, на которую вы стремитесь:
my $str = 'Absolute force';
$str =~ s/([eo])/$1 eq 'e' ? 'o' : 'e'/eg;
print $str;
Выходы:
Abseluto ferco
Обратите внимание, что LHS (левая сторона) соответствует как o
, так и e
, а RHS (справа) выполняет тест, чтобы увидеть, что соответствует и возвращает противоположное для замены.
Теперь, как правило, есть список слов, которые вы хотите заменить, поэтому удобно просто создавать хэш ваших значений from/to и динамически строить регулярное выражение. Следующее делает следующее:
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;
Выходы:
Hello, bar. How about foo? Never forget baz.
Это выше могло бы работать и для вашего случая e
и o
, но было бы излишним. Обратите внимание, как я использую quotemeta
, чтобы избежать ключей, если они содержат специальный символ регулярного выражения. Я также намеренно использовал группу без захвата вокруг них в $wordlist_re
, чтобы переменная могла быть сброшена в любое регулярное выражение и вести себя по желанию. Затем я помещаю группу захвата внутри s///
, потому что важно иметь возможность видеть, что захвачено в регулярном выражении, без необходимости возвращаться к значению интерполированной переменной.
из man sed
:
Командау/источник/приемник/ Транслитерайте символы в пространстве шаблонов, которые появляются в источнике, соответствующему символу в dest.
и tr
может сделать это тоже:
$ echo "Absolute force" | tr 'oe' 'eo'
Abseluto ferco
Лучше всего работает оператор tr///
. Однако, если вы хотите использовать оператор s///
(чтобы обрабатывать не только однократные замены), вы можете написать
$ echo 'Absolute force' | perl -pe 's/(e)|o/$1 ? "o" : "e"/eg'
Abseluto ferco
Скопирующие скобки избегают избыточного теста $1 eq 'e'
в ответе @Miller.