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

How to replace the characters in substring, including escape characters, with the character 'X'?

我想替换 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

除了文章"Is there a way to replace a substring with a same amount of X characters the length of it?",我没有找到任何内容,但是没有转义字符。
正则表达式 $s =~ s/(\Q$pattern\E)/'X' x length /e; 适用于任何字母数字替换字符串,但如果它包含 ()=,.-:;*

等特殊字符则无效

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

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

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{}/g;
    print;
}

 __DATA__
 abcdefg hijkl: (mnop-qrst) uvwx

我们:

  • 使用 'replacement strings' 的列表。
  • 使用映射生成替换(X x 长度)
  • 生成正则表达式以匹配 'search'
  • 然后用它来应用 'replace'

因此打印:

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

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

更新

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

请注意,最后一个模式在 ccddd:(eeef-ffgg) 之间有许多 space,但它正确匹配字符串

中的单个 space
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])/\/g;
  $item =~ s/\s+/\s+/g;
  $item;
} @patterns;
$pattern = qr/$pattern/;

while ( my $s = <DATA> ) {
  $s =~ s/($pattern)/ =~ 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

原版post

只需更换

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

s/(\Q$pattern\E)/ =~ 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)/ =~ 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