2015-06-30 14 views
-1

我有具有CSV文件模式的下面圖案perl的正則表達式選擇性地更換記錄分隔

(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的工作提供的解決方案適用於single {},但我發現自由流動的文本有一些嵌套{}。我嘗試修改perl onliner以適應沒有成功的嵌套花括號。 (1,2,3,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}。在此先感謝。

回答

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

您可以使用正則表達式,如果逗號後面]}沒有在它們之前,將檢查。

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

+0

我不能感謝你足夠IDEONE的解決方案和一個夢幻般的在線演示... – yuvi

+0

剛剛接受的答案是真的夠了。還有很多其他好的正則表達式測試網站(例如[debuggex.com](https://www.debuggex.com/))。 –

+0

如果您需要更多幫助,請告知我。 –