Конечно, вам придется адаптировать это к вашим потребностям (прежде всего цикл при чтении строк), но есть способ сделать это, который (на самом деле) не полагается на регулярные выражения. Как уже говорили другие, это отправная точка, вы можете адаптироваться к тому, что вам нужно.
#!/usr/bin/perl
use strict;
use warnings;
my $string = 'apple{{mango } guava ; banana; // pear berry;}';
my $new_string = join("\n", grep {/\S/} split(/(\W)/, $string));
print $new_string . "\n";
Это разбивает строку на массив, разбивая на несловарные символы, но сохраняя элемент. Затем greps для непробельных символов (удаляя элементы массива, содержащие пробелы). Затем объединяет элементы массива с символами новой строки в одну строку. Из того, что в вашей спецификации говорится, что вам нужно //
вместе, я оставлю это в качестве упражнения для читателя.
Edit:
Посмотрев на ваш запрос еще раз, вы получите определенную, но сложную структуру, которую вы пытаетесь проанализировать. Чтобы сделать это правильно, вам может понадобиться что-то более мощное, например, модуль Regexp::Grammars
. Это займет некоторое обучение, но вы можете определить очень сложный набор инструкций по синтаксическому анализу, чтобы сделать именно то, что вам нужно.
Редактировать 2:
Поскольку я искал причину узнать больше о Regexp::Grammars
, я воспользовался этой возможностью. Это основной пример, который я придумал. Он распечатывает проанализированную структуру данных в файл с именем "log.txt". Я знаю, что это не похоже на структуру, о которой вы просили, но она содержит всю эту информацию и может быть воссоздана так, как вам нравится. Я сделал это с помощью рекурсивной функции, которая в основном противоположна синтаксическому анализатору.
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use Regexp::Grammars;
my $grammar = qr{
<nocontext:>
<Line>
<rule: Line> <[Element]>*
<rule: Element> <Words> | <Block> | <Command> | <Comment>
<rule: Command> <[Words]> ;
<rule: Block> \{ <[Element]>* \}
<rule: Comment> // .*? \s{2,} #/ Syntax Highlighter fix
<rule: Words> (?:\b\w+\b) ** \s
}x;
my $string = 'apple{{mango kiwi } guava ; banana; // pear berry;}';
if ($string =~ $grammar) {
open my $log, ">", "log.txt";
print $log Dumper \%/; #/
print elements($/{Line}{Element});
} else {
die "Did not match";
}
sub elements {
my @elements = @{ shift() };
my $indent = shift || 0;
my $output;
foreach my $element (@elements) {
$output .= "\t" x $indent;
foreach my $key (keys %$element) {
if ($key eq 'Words') {
$output .= $element->{$key} . "\n";
} elsif ($key eq 'Block') {
$output .= "{\n" . elements($element->{$key}->{Element}, $indent + 1) . ("\t" x $indent) . "}\n";
} elsif ($key eq 'Comment') {
$output .= $element->{$key} . "\n";
} elsif ($key eq 'Command') {
$output .= join(" ", @{ $element->{$key}->{Words} }) . ";\n";
} elsif ($key eq 'Element') {
$output .= elements($element->{$key}, $indent + 1);
}
}
}
return $output;
}
Редактировать 3: В свете комментариев от ОП, я адаптировал приведенный выше пример, чтобы разрешить использование нескольких слов в одной строке, поскольку на данный момент эти слова могут быть разделены только одним пробелом. Я также сделал комментарии, совпадающие со всем, что начинается в //
и заканчивается двумя или более пробелами. Кроме того, так как я вносил изменения, и так как я считаю, что это довольно красивый код, я добавил табуляцию в блок форматирования блоков. Если это не желательно, это должно быть достаточно легко убрать. Иди сейчас и изучи Regexp::Grammars
и сделай так, чтобы она подходила для твоего конкретного случая. (Я знаю, я должен был заставить ОП сделать это изменение, но мне тоже нравится его изучать)
Редактировать 4: Еще одна вещь, если на самом деле вы пытаетесь восстановить полезный код из сериализованного в однострочный код, ваша единственная реальная проблема - извлечь строчные комментарии и отделить их от полезного кода (при условии, что вы используете пробел, игнорирующий язык, который выглядит так, как будто вы). Если это так, то, возможно, попробуйте этот вариант моего исходного кода:
#!/usr/bin/perl
use strict;
use warnings;
my $string = 'apple{{mango } guava ; banana; // pear berry;}';
my $new_string = join("\n", split(/((?:\/\/).*?\s{2,})/, $string));
print $new_string . "\n";
чей вывод
apple{{mango } guava ; banana;
// pear
berry;}