perl regex有选择地替换记录分隔符

时间:2015-06-30 07:53:06

标签: regex perl

我有一个CSV文件,其格式如下

(rupert, paul, 23, 8, [{fin, dan, jack},{bill,34,26,49},{84,28}],{34,jack,bon})

“{}”和“[]”中的CSV应替换为竖线字符“|”。格式化的输出应如下所示。

(rupert, paul, 23, 8, [{fin| dan| jack}|{bill|34|26|49}|{84|28}],{34|jack|bon})

我想使用Perl正则表达式,但我无处可去。非常感谢任何帮助。

perl guru提供的解决方案适用于单{}但是我发现自由流动的文本有一些嵌套的{}。我尝试修改perl onliner以适应嵌套的花括号,但没有成功。

(1,2,DER,赌注,NA,4,5-,{A,B,1,2-,SD [{1,2},{4,5}],C {Q,EW,3, 4},1,2,3-,CF {2,4,5,8},6}。

解决方案

(1,2,DER,赌注,NA,4,5-,{A,B,1,2-,SD [{1 | 2},{4 | 5}],C {Q | EW | 3 | 4},1,2,3-,CF {2 | 4 | 5 | 8} |。6}

但需要的是

(1,2,DER,赌注,NA,4,5-,{A | B | 1 | 2 | SD [{1 | 2} | {4 | 5}] | C {Q | EW | 3 | 4} | 1 | 2 | 3 | CF {2 | 4 | 5 | 8} |。6}

提前致谢。

3 个答案:

答案 0 :(得分:3)

您可以使用正则表达式来检查逗号后面是]还是},而不是前面的。{/ p>

my $s = "(rupert, paul, 23, 8, [{fin, dan, jack},{bill,34,26,49},{84,28}],{34,jack,bon})\n(rupert, paul, 23, 8, [{fin| dan| jack}|{bill|34|26|49}|{84|28}],{34|jack|bon})"; 
$s =~ s/,(?=(?:\{[^{}]*\}|[^{}])*})|,(?=(?:\[[^\[\]]*\]|[^\[\]])*\])/|/g;
print "$s\n";

请参阅IDEONE demo

这是regex demo

答案 1 :(得分:2)

您可以逐字逐句地查看字符串,记住您在括号中的深度,并在需要时用竖线替换逗号。

#!/usr/bin/perl
use warnings;
use strict;

my $string = '(rupert, paul, 23, 8, [{fin, dan, jack},{bill,34,26,49},{84,28}],{34,jack,bon})';

my $inside;
for my $pos (0 .. length($string) - 1) {
    my $char = substr $string, $pos, 1;
    $inside++ if $char =~ /[[{]/;
    $inside-- if $char =~ /[]}]/;
    substr $string, $pos, 1, '|' if ',' eq $char && $inside;
}
print $string, "\n";

答案 2 :(得分:0)

,(?=[^\[{}]*(?:\]|}))

您可以尝试此操作并替换为|。请参阅演示。

https://regex101.com/r/cK4iV0/3