Подтвердить что ты не робот

Перемещение букв с регулярным выражением

Как я могу поменять букву 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

4b9b3361

Ответ 1

Используйте оператор транслитерации:

$str =~ y/oe/eo/;

например.

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

Ответ 2

Как уже было сказано, способ сделать это - 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///, потому что важно иметь возможность видеть, что захвачено в регулярном выражении, без необходимости возвращаться к значению интерполированной переменной.

Ответ 3

из man sed:

у/источник/приемник/               Транслитерайте символы в пространстве шаблонов, которые появляются в источнике, соответствующему символу в dest.

Команда

и tr может сделать это тоже:

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

Ответ 4

Лучше всего работает оператор tr///. Однако, если вы хотите использовать оператор s/// (чтобы обрабатывать не только однократные замены), вы можете написать

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

Скопирующие скобки избегают избыточного теста $1 eq 'e' в ответе @Miller.