从正则表达式组中删除某些字符

时间:2019-04-29 17:12:18

标签: regex perl

我有一个像这样的字符串(键:: [“ 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

我想删除该选择字符串中的“,我想知道是否存在使用replace命令执行此操作的简便方法。所需结果...

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

如何解决此问题?

4 个答案:

答案 0 :(得分:4)

如果您的字符串确实具有"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}}

  • 如果$1甚至$2都没有捕获到任何内容,则表示没有匹配,结果就是$1不变,<安静地。因此,如果这种替换应始终有效,那么您可能希望添加对此类意外数据的处理

  • 不需要上面的$string,但可以返回$n

或者,尝试使用环视

($1 =~ s/",\s*"/ /gr) . $e

什么会减少代码量,但是以后使用起来可能会比较棘手。

虽然这是对我认为最不易维护的问题的直接答案。


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

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

在环顾四周示例中,我们需要再添加一些

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

因为$string =~ s{...}{ (my $n = $1) =~ s/",\s*"/ /g; $n }gr 运算符会返回进行替换的次数,而我们需要从s/(替换端)的整个代码中返回$n,以此作为替换。

答案 1 :(得分:1)

您的文本几乎是 正确的JSON,因此很容易做到这一点,然后进行处理:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say postderef/;
no warnings qw/experimental::postderef/;
use JSON::XS; # Install through your OS package manager or a CPAN client

my $str = q/"emailDomains":["google.co.uk","google.com","google.com","google.com","google.co.uk"]/;
my $json = JSON::XS->new();

my $obj = $json->decode("{$str}");
my $fixed = $json->ascii->encode({emailDomains =>
                                    join(', ', $obj->{'emailDomains'}->@*)});
$fixed =~ s/^\{|\}$//g;
say $fixed;

答案 2 :(得分:1)

您可以使用基于\G的正则表达式开始与:["进行匹配,并进一步捕获相应的值并替换匹配的文本,从而仅保留逗号并删除双引号。

(:\[")|(?!^)\G([^"]+)"(,)"

Regex Demo

答案 3 :(得分:0)

尝试使用正则表达式:" *, *"

替换为:,

Demo