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";

我正在尝试编写一个正则表达式,它将删除除数字和N/Aor之外的所有内容NA

为此,我需要将此正则表达式否定/(n\/a|na|\d+)/i.

我试过这个正则表达式:

s/[^(na|n\/a|\d+)]//gi

最终归结为:

s/[^\d+na()\/|]//ig;

我该怎么办?

4

3 回答 3

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"在列表上下文中评估为。
该列表被连接起来,然后代表所需的输出。

于 2013-04-03T09:20:21.103 回答
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启用单行模式,允许.*跨换行符匹配。

一般来说,正则表达式中的匹配往往非常困难。大多数负匹配问题实际上可以表示为匹配,这样做通常更简单。

于 2013-04-03T09:06:05.410 回答
0
s/[^na\d]|n(?!\/?a)|(?<!n)(?<!n\/)a//ig

注意:我认为您不能替换(?<!n)(?<!n\/)为,(?<!n\/?)但您可以尝试。

于 2013-04-03T09:02:06.410 回答