簡體   English   中英

如何在Perl中的匹配大括號之間提取字符串?

[英]How can I extract a string between matching braces in Perl?

我的輸入文件如下:

HEADER 
{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}

{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}

{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}

{ABC|*|XYZ:ghi:jkl {JKL 0 372 0} {{Points {}}}}

{ABC|*|XYZ:mno:pqr {GHI 0 34 0} {{Points {}}}}

{
    ABC|*|XYZ:abc:pqr {GHI 0 68 0}
        {{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
        }
TRAILER

我想將文件解壓縮到如下數組:

$array[0] = "{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}"

$array[1] = "{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}"

$array[2] = "{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}"

..
..

$array[5] = "{
    ABC|*|XYZ:abc:pqr {GHI 0 68 0}
        {{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
        }"

這意味着,我需要將第一個開口花括號與其閉合花括號相匹配,並在其間提取弦。

我已查看以下鏈接,但這不適用於我的問題。 正則表達式在花括號之間獲取字符串“{我想在花括號之間有什么}}”

我正在努力,但如果有人可以幫助我完成他們的專業知識,我會很有幫助

謝謝斯里蘭卡

至少在現代版本的Perl中,這肯定可以用正則表達式完成:

my @array = $str =~ /( \{ (?: [^{}]* | (?0) )* \} )/xg;

print join "\n" => @array;

正則表達式匹配一個大括號塊,它包含非大括號字符或遞歸到自身(匹配嵌套大括號)

編輯:上面的代碼在Perl 5.10+中工作,對於早期版本,遞歸有點冗長:

my $re; $re = qr/ \{ (?: [^{}]* | (??{$re}) )* \} /x;

my @array = $str =~ /$re/xg;

我第二個建議使用Text::Balanced模塊。 幾行將幫助您前進。

use strict;
use warnings;
use Text::Balanced qw/extract_multiple extract_bracketed/;

my $file;
open my $fileHandle, '<', 'file.txt';

{ 
  local $/ = undef; # or use File::Slurp
  $file = <$fileHandle>;
}

close $fileHandle;

my @array = extract_multiple(
                               $file,
                               [ sub{extract_bracketed($_[0], '{}')},],
                               undef,
                               1
                            );

print $_,"\n" foreach @array;

OUTPUT

{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}
{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}
{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}
{ABC|*|XYZ:ghi:jkl {JKL 0 372 0} {{Points {}}}}
{ABC|*|XYZ:mno:pqr {GHI 0 34 0} {{Points {}}}}
{
    ABC|*|XYZ:abc:pqr {GHI 0 68 0}
        {{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
        }

我不認為純正則表達式是你想要在這里使用的(恕我直言,這可能甚至不能使用正則表達式進行解析)。

相反,構建一個小解析器,類似於此處顯示的: http ://www.perlmonks.org/?node_id = 308039(請參閱dbgunefx(Parson)於2003年11月18日18:29 UTC的回答)

更新似乎它可能是正則表達式 - 我在Mastering正則表達式中看到了匹配嵌套括號的引用(可以在Google Books上找到,因此如果你沒有這本書就可以用Google搜索 - 參見第5章,節“匹配平衡的括號集“)

您可以隨時計算大括號:

my $depth = 0;
my $out = "";
my @list=();
foreach my $fr (split(/([{}])/,$data)) {
    $out .= $fr;
    if($fr eq '{') {
        $depth ++;
    }
    elsif($fr eq '}') {
        $depth --;
        if($depth ==0) {
            $out =~ s/^.*?({.*}).*$/$1/s; # trim
            push @list, $out;
            $out = "";
        }
    }
}
print join("\n==================\n",@list);

這是舊的,簡單的Perl風格(可能很難看)。

對於這種類型的解析,使用狀態機比使用正則表達式要好得多。

正則表達式對於匹配大括號實際上非常糟糕。 根據你想要的深度,你可以為Parse :: RecDescent寫一個完整的語法(比聽起來容易得多!)。 或者,如果您只想獲取塊,請搜索打開“{”標記並關閉“}”,並記住在任何給定時間打開的數量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM