首页 > 解决方案 > 从正则表达式组中删除某些字符

问题描述

我有一个看起来像这样的字符串 (key":["value","value","value"])

"emailDomains":["google.co.uk","google.com","google.com","google.com","google.co.uk"]

我使用以下正则表达式从字符串中进行选择。(正则表达式的设置方式不会选择看起来像这样的字符串 "key":[{"key":"value","key":"value"}] )

(?<=:\[").*?(?="])

结果选择:

google.co.uk","google.com","google.com","google.com","google.co.uk

我想删除该选择字符串中的“,我想知道是否有一种简单的方法可以使用替换命令来做到这一点。期望的结果......

"emailDomains":["google.co.uk, google.com, google.com, google.com, google.co.uk"]

我该如何解决这个问题?

标签: regexperl

解决方案


如果您的字符串确实具有 形式"key":["v1", "v2", ... "vN"],您可以拆分需要更改的部分,","用其中的空格替换,然后重新组合:

my @parts = split / (\["\s* | \s*\"]) /x, $string;    #"

$parts[2] =~ s/",\s*"/ /g;

my $processed = join '', @parts;

分隔符的正则表达式模式split被捕获,因为在这种情况下,分隔符也在返回的列表中,这有助于将字符串重新组合在一起。然后,我们需要更改数组的第三个元素。

在这种方法中,我们必须更改数组中的特定元素,因此如果您的格式发生变化,即使有一点点,这可能不(或仍然可能)合适。

这当然应该使用模块作为 JSON 处理。如果格式不确定,如评论中所述,最好尝试确保您拥有 JSON。一旦需求慢慢开始演变,挑选像上面(或下面)这样的点点滴滴是一条疯狂之路。


可以在正则表达式中使用相同的方法,这实际上可能具有一个优势,即能够挖掘并忽略前面的所有内容:split如果格式不完全如图所示,该部分可能会以多个元素结束,什么然后影响一切)

$string =~ s{ :\["\s*\K (.*?) ( "\] ) }{ 
    my $e = $2; 
    my $n = $1 =~ s/",\s*"/ /gr; 
    $n.$e 
}ex;

这里/e的修饰符使得替换端被评估为代码,我们与split上面的操作相同。正则表达式注意事项

  • 必须先保存$2,因为它会在下一个正则表达式中重置

  • /r修饰符不会改变其目标,而是返回改变后的字符串,它允许我们在只读文件上使用替换运算符$1

  • 如果什么都没有被捕获$2,也许$1,那意味着没有匹配,结果就是$string没有改变,悄悄地。因此,如果这种替换应该始终有效,那么您可能需要添加对此类意外数据的处理

  • 不需要$n以上,但可以返回($1 =~ s/",\s*"/ /gr) . $e

或者,尝试使用环视

$string =~ s{ (?<=:\[") (.+?) (?="\]) }{ $1 =~ s/",\s*"/ /gr }egx;

什么确实减少了代码量,但以后使用可能会更棘手。

虽然这是对这个问题的直接回答,但我认为它是最不可维护的。


  这个有用的修饰符,用于“非破坏性替换”,出现在 v5.14 中。在早期的 Perl 版本中,我们会复制字符串并在其上运行正则表达式,使用习语

(my $n = $1) =~ s/",\s*"/ /g;

在lookarounds-example中,我们需要更多

$string =~ s{...}{ (my $n = $1) =~ s/",\s*"/ /g; $n }gr

因为s/运算符返回在我们需要$n从(替换端)中的整段代码返回时所做的替换次数{},以用作替换。


推荐阅读