我想在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;
适用于任何字母数字替换字符串,但如果它包含()=,.-:;*
等特殊字符
在上面的例子中,输入和替换字符串都可以包含特殊字符。
答案 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
我们:
因此打印:
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