Лучший способ скопировать и продублировать каждую строку входного файла, в то время как регулярное выражение модифицирует дублированную строку - PullRequest
1 голос
/ 04 февраля 2010

Этот вопрос состоит из 2 разделов: один для "согласования одной строки" и один для "согласования многострочной области". Кроме того, у меня есть полу-рабочее решение, я хочу найти больше надежности и элегантности в своем решении.

  1. Однострочный матч: Я хотел бы продублировать каждую строку входного файла так, чтобы вторая строка была модификацией первого регулярного выражения: Е.Г.

File.txt

YY BANANA, YYZ, ABC YHZ YY1
YY APPLE , YYZ, ABC YHZ YY1
YY ORANGE, YYZ, ABC YHZ YY1
YZ GRAPE , YZZ, ABC YHZ YZ1

СТАНЕТ:

YY BANANA, YYZ, ABC YHZ YY1
XY BANANA, XYZ, ABC YHZ XY1
YY APPLE , YYZ, ABC YHZ YY1
XY APPLE , XYZ, ABC YHZ XY1
YY ORANGE, YYZ, ABC YHZ YY1
XY ORANGE, XYZ, ABC YHZ XY1
YZ GRAPE , YZZ, ABC YHZ YZ1
XZ GRAPE , XZZ, ABC YHZ XZ1

Имейте в виду, что реальный файл большой, и пример YY -> XY и YZ -> XZ Иными словами, в моем случае дела YY, YH, YZ, Y1, Y2, Y3 являются символы, которые я хотел бы изменить на XY, XH, XZ, X1, X2, X3.

Я сделал что-то в PERL, что очень сырой (создам ссылку на это как в качестве отправной точки, чтобы показать, о чем я думал) Но написанный мной Perl-скрипт не является элегантным или общим и требует многократного передает файл.

Мой сырой удар .... В ПЕРЛ. http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/perl-sed-awk/conditional-duplicate/

Использование моего сырого удара:

MatchDuplicate.pl  INPUT.txt YY XY > INPUT2.txt
MatchDuplicate.pl  INPUT2.txt YH XH > INPUT3.txt
MatchDuplicate.pl  INPUT3.txt Y1 X1 > INPUT4.txt
MatchDuplicate.pl  INPUT4.txt Y2 X2 > INPUT5.txt

INPUT5.txt используется ...

  1. Multi Line Match Точно так же, как указано выше, но каждая «запись» ввода будет соответствовать нескольким строкам:

File.txt

< some starting marker...startRecord:>
data
data
YY data
YY BANANA, YYZ, ABC YHZ YY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
YY data
YY APPLE , YYZ, ABC YHZ YY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
YY data
YY ORANGE, YYZ, ABC YHZ YY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
YZ data
YZ GRAPE , YZZ, ABC YHZ YZ1
<some ending record marker>

СТАНЕТ:

< some starting marker...startRecord:>
data
data
YY data
YY BANANA, YYZ, ABC YHZ YY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
XY data
XY BANANA, XYZ, ABC YHZ XY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
YY data
YY APPLE , YYZ, ABC YHZ YY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
XY data
XY APPLE , XYZ, ABC YHZ XY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
YY data
YY ORANGE, YYZ, ABC YHZ YY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
XY data
XY ORANGE, XYZ, ABC YHZ XY1
<some ending record marker>
< some starting marker...startRecord:>
data
data
YZ data
YZ GRAPE , YZZ, ABC YHZ YZ1
<some ending record marker>
< some starting marker...startRecord:>
data
data
XZ data
XZ GRAPE , XZZ, ABC YHZ XZ1
<some ending record marker>

My Raw Stab: http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/perl-sed-awk/multi-line-conditional-duplicate/

Ответы [ 3 ]

2 голосов
/ 04 февраля 2010

Это решит ваш первый вопрос:

use strict;
use warnings;

die "usage..." unless @ARGV == 3;
my ($file, $src, $dst) = @ARGV;

open my $fh, '<', $file or die "Can not open $file: $!";
while (<$fh>) {
    print;
    if (/^$src\b/) {
        s/$src/$dst/g;
        print;
    }
}
close $fh;

Глядя на ваши связанные скрипты ... вы можете легко конвертировать ваши блочные комментарии в POD, чтобы они фактически стали страницей руководства для вашего кода. Тогда вы можете использовать POD :: Usage чтобы получить информацию об использовании, когда пользователь делает что-то глупое.

2 голосов
/ 04 февраля 2010

Для 1:

while(<>) {
    say $_;
    say $_ if s/$pattern/$replacement/;
}

Добавьте соответствующие файловые ручки и другой шаблон.

РЕДАКТИРОВАТЬ: Давайте пойдем на что-то более общее, чем.

Сначала мы разберем наши аргументы командной строки и поместим наши замены в хеш:

$filename = shift @ARGV;
%patterns = ();
while (scalar @ARGV) {
    my $pattern = shift @ARGV;
    my $replacement = shift @ARGV;
    $patterns{$pattern} = $replacement
}

Затем для каждой строки в файле мы выведем дословно строку и посмотрим, соответствует ли она какой-либо из наших моделей.

while (<>) {
    say $_;
    while (my ($pattern, $replacement) = each %patterns) {
        s/$pattern/$replacement/g and say $_ if /^$pattern/;
    }
}
1 голос
/ 04 февраля 2010

Если маркер конца записи одинаков для всех записей, вы можете установить переменную $/, чтобы <FILE> считывал по одной записи за раз.

$\ = "<some ending record marker>\n";
while (<FILE>) {
    print $_;
    # $_ is a multi-line string so use /m modifier
    print $_ if s/$pattern/$replacement/m;
}
...