1

Предположим, я хочу заменить все AAA с BBB и все BBB с AAA в текстовом файле.

Вот что выглядит очевидным решением (в Perl или в Sed):

с / ААА / ВВВ / г; с / В / ААА / г;

Но это не работает, потому что после замены AAA на BBB можно заменить его на AAA.

Какие решения для этой проблемы существуют?

Может быть, вы можете предоставить некоторый Perl (или Python или любой другой) код?

2 ответа2

2

В Perl, вы можете использовать /e флаги е код valuate в сменной части подстановки:

s/(AAA|BBB)/'AAA' eq $1 ? 'BBB' : AAA/ge

Объяснение:

  • (AAA|BBB) соответствует AAA или BBB и сохраняет соответствующую строку в $ 1.
  • condition ? true : false - это "троичный оператор". Он возвращает значение "истина", если "условие" истинно, и "ложь" в противном случае. Таким образом, в этом случае он возвращает строку для использования для замены.
  • /ge означает "глобально", то есть не просто один раз в строке, а "eval", то есть заменяет заменяющую часть как код для запуска.
1

О, я нашел модуль, который делает это:

perl -MReplaceMultiple -e 'print replace_multiple({"AAA" => "BBB", "BBB" => "AAA"}, "AAABBB"), "\n";'

ReplaceMultiple.pm:

package ReplaceMultiple;

use strict;
use warnings;

our (@ISA, @EXPORT);
require Exporter; @ISA = qw(Exporter);
@EXPORT = qw(replace_multiple_inplace replace_multiple);

sub replace_multiple_inplace {
  my ($hash, $str_ref) = @_;
  my $obj = ReplaceMultiple->new($hash);
  return $obj->apply_inplace($str_ref);
}

sub replace_multiple {
  my ($hash, $str) = @_;
  my $obj = ReplaceMultiple->new($hash);
  return $obj->apply($str);
}

sub new {
  my ($class, $hash) = @_;
  my $re_str = "(" . (join '|', map { "\Q$_\E" } keys %$hash) . ")";
  my $self = bless {HASH=>$hash, RE=>qr/$re_str/}, $class;
  return $self;
}

sub apply_inplace {
  my ($self, $str_ref) = @_;
  $$str_ref =~ s/$self->{RE}/$self->{HASH}{$1}/g;
  return $$str_ref;
}

sub apply {
  my ($self, $str) = @_;
  my $str2 = $str;
  return $self->apply_inplace(\$str2);
}

1;

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .