Мой входной файл как указано ниже:
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}}}}
}"
Что означает, я должен соответствовать первой вводной изогнутой фигурной скобке ее заключительной изогнутой фигурной скобке и извлечь промежуточную строку.
Я проверил ссылку ниже, но это не относится к моему вопросу. Regex для получения строки между фигурными скобками "{я хочу то, что между фигурными скобками}"
Я пробую, но действительно помог бы, если кто-то может помочь мне с их экспертными знаниями...
Спасибо Sri...
Это, безусловно, можно сделать с помощью регулярного выражения, по крайней мере, в современных версиях Perl:
my @array = $str =~ /( \{ (?: [^{}]* | (?0) )* \} )/xg;
print join "\n" => @array;
Регулярное выражение соответствует блоку фигурных скобок, который содержит символы, не являющиеся фигурными скобками, или рекурсию в себя (соответствует вложенным фигурным скобкам)
Изменить: приведенный выше код работает в Perl 5.10+, для более ранних версий рекурсия немного более подробна:
my $re; $re = qr/ \{ (?: [^{}]* | (??{$re}) )* \} /x;
my @array = $str =~ /$re/xg;
Вы всегда можете сосчитать фигурные скобки:
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 (и, вероятно, уродливый).
Второе предложение ysth использовать модуль 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;
{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 (см. Ответ shotgunefx (Парсон) 18 ноября 2003 г., 18:29 UTC)
ОБНОВЛЕНИЕ Кажется, это можно сделать с помощью регулярного выражения - я видел ссылку на сопоставление вложенных круглых скобок в Освоение регулярных выражений (доступно на Google Книги и, следовательно, их можно найти в Google, если у вас нет книги - см. Главу 5, раздел «Соответствие сбалансированным наборам круглых скобок»)
Регулярные выражения на самом деле очень плохо подходят для соответствия брекетам. В зависимости от того, насколько глубоко вы хотите углубиться, вы можете написать полную грамматику (что намного проще, чем кажется!) Для Parse :: RecDescent . Или, если вы просто хотите получить блоки, поищите открывающие '{' знаки и закрывающие '}' и просто подсчитайте, сколько из них открыто в любой момент времени.
Для этого типа синтаксического анализа гораздо лучше использовать конечный автомат, чем регулярное выражение.