从正则表达式组中删除特定字符

3
我有一个看起来像这样的字符串 (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

我想要删除选择字符串中的引号,我在想是否可以使用replace命令轻松实现此操作。期望结果...

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

我该如何解决这个问题?


1
看起来你正在尝试解析JSON,我建议使用一个JSON解析模块。 - AKHolland
这是确实如此,但我仍然想知道是否有一种好的方法来进行这种替换。@AKHolland - Muamer Bektić
4个回答

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

在这个示例中,我们需要更多的“查找周围”的内容。
$string =~ s{...}{ (my $n = $1) =~ s/",\s*"/ /g; $n }gr

由于s / 运算符返回进行替换的数量,而我们需要在整个{}代码段(替换侧)中返回$n以用作替换。


1
@MuamerBektić 如果您的输入格式不同,我们需要更多了解它才能建议“最佳”方法(这很困难)。我添加了一个正则表达式,根据输入格式可能具有特定优势。 - zdim
1
@MuamerBektić 添加了另一种使用正则表达式的方法(但与第一个正则表达式相比没有任何优势,除了它更短并使用了您尝试过的环视)。 - zdim
1
@MuamerBektić "问题的一个重要部分是我不知道所有表格可能是什么" -- 是的,这确实是最大的问题。您需要了解数据可能存在哪些变化。 (一种--痛苦的--方法是处理,查看未成功的内容,进行调整...重复。) - zdim
1
@MuamerBektić 呃...在大正则表达式的替换部分使用的正则表达式吗?您能调试它并进行微调,直到错误消失吗?例如,将 /",\s*"/ 更改为 /,/ 等(您是否正确复制和粘贴?我的代码中有一些愚蠢的打字错误吗?) - zdim
1
@MuamerBektić 啊!v5.10版本还没有/r修饰符。好的,已经编辑过了。 - zdim
显示剩余8条评论

1

您的文本几乎是正确的JSON格式,所以只需轻松地进行最后一步即可将其转换为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;

问题在于我没有创建JSON,所以我不知道它有多接近正确的JSON格式。数据大约有300-500种不同的形式,这是我目前仍然无法处理的唯一问题。我正在尝试将所有数据解析成键值对并将其插入到表格中。 - Muamer Bektić
1
@MuamerBektić 尝试使用常规表达式处理JSON或HTML这样的结构化数据格式,这将带来痛苦和折磨,并且存在各种问题。这就是为什么我的答案使用了一个理解格式的模块。这样做更容易、更健壮。这也使得“插入到表格”变得更加容易,因为这样你可以直接访问值,而不是这种奇怪的非完整JSON输出。从声音中听起来,这里有一个XY问题 - Shawn

1
你可以使用基于 \G 的正则表达式来从 :[" 开始匹配,并适当捕获值并替换匹配的文本,以便仅保留逗号并删除双引号。
(:\[")|(?!^)\G([^"]+)"(,)"

正则表达式演示


这似乎做到了我想要的,但是我尝试在Perl中实现它,但好像不起作用?$msgPayload =~ s/(:[")|(?!^)\G([^"]+)"(,)"/$1$2$3/g; 除非我漏掉了什么,否则我不确定哪里出了问题。 - Muamer Bektić

0
尝试正则表达式:" *, *" 替换为:, 演示

我知道我可以这样做,但是我希望它只在':['和']'之间进行替换,这就是我卡住的地方。 - Muamer Bektić

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接