初学正则表达式:多个替代对象(Beginner Regex: Multiple Replaces)

2019-08-16 19:40发布

我有一个字符串:

$mystring = "My cat likes to eat tomatoes.";

我想做这个字符串的正则表达式2层的替代品。 我想要做的s/cat/dog/s/tomatoes/pasta/ 。 不过,我不知道如何正确格式化的正则表达式做多的替代品在一个表达,在同一行,在一个声明。 现在,我的一切是:

$mystring =~ s/cat/dog/ig;
$mystring =~ s/tomatoes/pasta/ig;

Answer 1:

我的建议是你这样做

my $text               =  'My cat likes to eat tomatoes.';
my ( $format = $text ) =~ s/\b(cat|tomatoes)\b/%s/g;

然后,你可以这样做:

my $new_sentence = sprintf( $format, 'dog', 'pasta' ); 

除了这一点:

$new_sentence    = sprintf( $format, 'tiger', 'asparagus' );

我去的其他人。 你不应该做到这一切在一个表达,或一条线......但这里是一个方法:

$text =~ s/\b(cat|tomatoes)\b/ ${{ qw<cat dog tomatoes pasta> }}{$1} /ge;


Answer 2:

与往常一样,使用散列为查找表,匹配键,其值替换:

#!/usr/bin/perl

use strict;
use warnings;

use Regex::PreSuf;

my %repl = (
    cat => 'dog',
    tomatoes => 'pasta',
);

my $string = "My cat likes to eat tomatoes.";
my $re = presuf( keys %repl );

$string =~ s/($re)/$repl{$1}/ig;

print $string, "\n";

输出:

C:\Temp> t
My dog likes to eat pasta.

你也可以使用一个循环:

for my $k ( keys %repl ) {
    $string =~ s/\Q$k/$repl{$k}/ig;
}


Answer 3:

你为什么要?

我知道一些的Perl-ERS引以为豪的是能够写出一些最混淆代码想象(看到一些关于这里的代码高尔夫球题),但这并不使它成为一个聪明的做法。

保持它的可读性,只要保持这样你会感谢自己的长远。

编辑:

当然,如果你正在寻找5层或更多的替代品,请(在上帝的母亲)使用某种类型的查找表。 但不要试图写一个巨大的正则表达式,做这一切。



Answer 4:

如果你正在寻找的东西是正则表达式本身,直接查找表的perl @SinanÜnür将无法正常工作(如字符串相等123 eq '\d+'失败)。

您可以使用Regexp::Assemble来解决这个限制:

use strict;
use warnings;
use Regexp::Assemble;

my %replace = (
    'cat' => 'dog',
    '(?:tom|pot)atoes' => 'pasta',
);
my $re = Regexp::Assemble->new->track(1)->add(keys %replace);

my $str = 'My cat likes to eat tomatoes.';
while (my $m = $re->match($str)) {
    $str =~ s/$m/$replace{$m}/;
}
print $str, $/;

$str = 'My cat likes to eat potatoes.';
while (my $m = $re->match($str)) {
    $str =~ s/$m/$replace{$m}/;
}
print $str, $/;

这两个区块的产生My dog likes to eat pasta.



Answer 5:

在一个单行进行多重替换的一个非常基本的方法是与分组匹配文本。 这会不会让你找到“猫”的所有实例,并与“狗”取代它,但它会带你到“我的狗喜欢吃面食”

$mystring =~ s/(.*)cat(.*)tomatoes(.*)/$1dog$2pasta$3/g;


Answer 6:

你可以这样做的快速和肮脏的方式,或快速和清洁方式:

在这两种情况下,你需要一个散列word => replacement

“|”随着快速和肮脏的方式,然后你通过用加入哈希键建立替代的左侧部分。 为了应对重叠词(如“猫”和“catogan”),您需要先放置最长的选项,做一个sort reverse散列的键。 您仍然可以不与词元字符处理来代替(如“猫++”)。

快速和清洁的方式使用正则表达式::组装构建正则表达式的左侧部分。 它与叠词本身的交易,它是简单的把它处理的字样元字符来代替。

一旦你的字代替,然后你在散列中的相应条目替换它。

下面是一些代码,显示2种方法,处理各种情况:

#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 6;

use Regexp::Assemble;

my $mystring = "My cat likes to eat tomatoes.";
my $expected = "My dog likes to eat pasta.";

my $repl;

# simple case
$repl= { 'cat' => 'dog', 'tomatoes' => 'pasta', };

is( 
    repl_simple($mystring, $repl), 
    $expected, 
    'look Ma, no module (simple)'
);  

my $re= regexp_assemble($repl);
is( 
    repl_assemble($mystring, $re), 
    $expected, 
    'with Regex::Assemble (simple)'
);

# words overlap
$mystring = "My cat (catogan) likes to eat tomatoes.";
$expected = "My dog (doggie) likes to eat pasta.";

$repl= {'cat' => 'dog', 'tomatoes' => 'pasta', 'catogan'  => 'doggie', };

is( 
    repl_simple($mystring, $repl), 
    $expected, 
    'no module, words overlap'
);  

$re= regexp_assemble( $repl);
is( 
     repl_assemble($mystring, $re), 
     $expected, 
     'with Regex::Assemble, words overlap'
);


# words to replace include meta-characters
$mystring = "My cat (felines++) likes to eat tomatoes.";
$expected = "My dog (wolves--) likes to eat pasta.";

$repl= {'cat' => 'dog', 'tomatoes' => 'pasta', 'felines++' => 'wolves--', };

is( 
    repl_simple($mystring, $repl), 
    $expected, 
    'no module, meta-characters in expression'
);  

$re= regexp_assemble( $repl);
is( 
    repl_assemble($mystring, $re), 
    $expected, 
    'with Regex::Assemble, meta-characters in expression'
);

sub repl_simple { 
    my( $string, $repl)= @_;
    my $alternative= join( '|', reverse sort keys %$repl);
    $string=~ s{($alternative)}{$repl->{$1}}ig;
    return $string;
  }


sub regexp_assemble { 
    my( $repl)= @_;
    my $ra = Regexp::Assemble->new;
    foreach my $alt (keys %$repl)
      { $ra->add( '\Q' . $alt . '\E'); }
    return $ra->re;
  } 

sub repl_assemble { 
    my( $string, $re)= @_;
    $string=~ s{($re)}{$repl->{$1}}ig;
    return $string;
  }


文章来源: Beginner Regex: Multiple Replaces