我有一个字符串:
my $str = "asd na ann nna aannaa NA 10012 3212and123 complan-boy
NANANANA n/a n/a nn/a na/a n/a/a";
我正在尝试编写一个正则表达式,除了数字和N/A
或NA
之外,还会删除所有内容。
为此,我需要将此正则表达式的 否定 设为/(n\/a|na|\d+)/i
。
我试过这个正则表达式:
s/[^(na|n\/a|\d+)]//gi
最终归结为:
s/[^\d+na()\/|]//ig;
我该怎么办?
答案 0 :(得分:3)
正如一些评论中指出的那样,优雅的方式是采取你想要保留的东西,而忘记其余的:
use Test::More tests => 1;
my $str = "asd na ann nna aannaa NA 10012 3212and123 complan-boy
NANANANA n/a n/a nn/a na/a n/a/a";
my $replaced = join '' => $str =~ m{n/?a|\d+}gi;
is $replaced, 'nananaNA100123212123NANANANAn/an/an/anan/a';
我发现这与复杂的外观相比非常简单和可维护。您需要知道的是,在列表上下文中,未定义捕获组的全局正则表达式匹配会返回所有匹配的子字符串的列表。例如。 "foo" =~ /o/g
会在列表上下文中评估为"o", "o"
此列表连接在一起,然后表示所需的输出。
答案 1 :(得分:2)
一种简单的方法是找到任何后跟n / a或数字(或字符串结尾)的东西,然后只用n / a或数字部分替换它。
use warnings;
use strict;
my $str = "asd na ann nna aannaa NA 10012 3212and123 complan-boy
NANANANA n/a n/a nn/a na/a n/a/a";
$str =~ s#.*?(n/?a|\d+|\z)#$1#gis;
print $str;
/s
启用单行模式,允许.*
匹配换行符。
一般来说,正则表达式中的否定匹配往往非常困难。大多数负匹配问题实际上可以表示为正匹配,这样做通常更简单。
答案 2 :(得分:0)
s/[^na\d]|n(?!\/?a)|(?<!n)(?<!n\/)a//ig
注意:我认为您不能将(?<!n)(?<!n\/)
替换为(?<!n\/?)
,但您可以尝试。