如何用字符“X”替换子字符串中的字符,包括转义字符?

时间:2015-06-26 08:00:25

标签: regex perl escaping substring

我想在perl脚本中替换给定字符串(包括转义字符)中的子字符串(包括转义字符)。如果可能,请使用正则表达式。

输入:

abcdefg hijkl: (mnop-qrst) uvwx
aabbccd deeff: (gghh-iijj) kkll
aaabbbc ccddd: (eeef-ffgg) ghhh

替换字符串示例:

ijkl:
gghh-iijj
ccddd: (eeef-ffgg)

输出:

abcdefg hXXXX: (mnop-qrst) uvwx
aabbccd deeff: (XXXX-XXXX) kkll
aaabbbc XXXXX: (XXXX-XXXX) ghhh

我没有找到任何东西,除了文章“有没有办法用相同数量的X字符替换长度的子字符串?”,但没有转义字符。
正则表达式$s =~ s/(\Q$pattern\E)/'X' x length $1/e;适用于任何字母数字替换字符串,但如果它包含()=,.-:;*等特殊字符

,则不适用

在上面的例子中,输入和替换字符串都可以包含特殊字符。

2 个答案:

答案 0 :(得分:2)

我建议的技巧是预先生成你的正则表达式模式。

use strict;
use warnings;


my @replace_strings = qw ( ijkl:
    mnop-qrst
    hijkl: );

my %replace = map { $_ => "X" x length($_) } @replace_strings;

my $replace_regex = join( "|", map {quotemeta} @replace_strings );
$replace_regex = qr/($replace_regex)/;

while (<DATA>) {
    s/$replace_regex/$replace{$1}/g;
    print;
}

 __DATA__
 abcdefg hijkl: (mnop-qrst) uvwx

我们:

  • 使用'替换字符串'列表。
  • 使用map生成替换(X x length)
  • 生成正则表达式以匹配“搜索”
  • 然后使用它来应用'替换'

因此打印:

abcdefg XXXXXX (XXXXXXXXX) uvwx

您可以使用类似的技巧。

继续发表评论 - 看起来您想要定义一些字符串,只需替换其中的文本即可。

那么这样的事情怎么样:

my %replace = map { $_ => ($_ =~ s/\w/X/gr) } @replace_strings;

(源数据上):

abcdefg hXXXX: (mnop-qrst) uvwx
aabbccd deeff: (XXXX-XXXX) kkll
aaabbbc XXXXX: (XXXX-XXXX) ghhh

(如果您想要替换它,可以将-添加到模式中。

答案 1 :(得分:1)

更新

这是一个解决方案,允许模式中的任何空格匹配目标字符串中的任何数量的空白。请注意,要执行此操作,我必须手动转义非单词字符,因此不再需要\Q ... \E

请注意,最后一个模式在ccddd:(eeef-ffgg)之间有很多空格,但它正确匹配字符串中的单个空格

use strict;
use warnings;

my @patterns = (
  'ijkl:',
  'gghh-iijj',
  'ccddd:            (eeef-ffgg)',
);

# Build and compile the regex
my $pattern = join '|', map {
  my $item = $_;
  $item =~ s/([^\w\s])/\\$1/g;
  $item =~ s/\s+/\\s+/g;
  $item;
} @patterns;
$pattern = qr/$pattern/;

while ( my $s = <DATA> ) {
  $s =~ s/($pattern)/$1 =~ tr{a-zA-Z0-9}{X}r/eg;
  print $s;
}

__DATA__
abcdefg hijkl: (mnop-qrst) uvwx
aabbccd deeff: (gghh-iijj) kkll
aaabbbc ccddd: (eeef-ffgg) ghhh

输出

abcdefg hXXXX: (mnop-qrst) uvwx
aabbccd deeff: (XXXX-XXXX) kkll
aaabbbc XXXXX: (XXXX-XXXX) ghhh

原帖

所有必要的是替换

s/(\Q$pattern\E)/'X' x length $1/e

s/(\Q$pattern\E)/$1 =~ tr{a-zA-Z0-9}{X}r/e

这是一个演示。请注意,/r修饰符需要Perl v5.14或更高版本

use strict;
use warnings;
use 5.014;

my @matches = (
  'ijkl:',
  'gghh-iijj',
  'ccddd: (eeef-ffgg)',
);

while ( my $s = <DATA> ) {
  $s =~ s/(\Q$_\E)/$1 =~ tr{a-zA-Z0-9}{X}r/e for @matches;
  print $s;
}

__DATA__
abcdefg hijkl: (mnop-qrst) uvwx
aabbccd deeff: (gghh-iijj) kkll
aaabbbc ccddd: (eeef-ffgg) ghhh

输出

abcdefg hXXXX: (mnop-qrst) uvwx
aabbccd deeff: (XXXX-XXXX) kkll
aaabbbc XXXXX: (XXXX-XXXX) ghhh