Perl, как ввести текст перед ключевым словом (совпадение) и сохранить остальное из файла

Я новичок в Perl, и мне нужно отредактировать текстовый файл, добавив некоторый текст после того, как я найду ключевое слово (соответствие), мне нужно сохранить изменения в том же файле, но сохранить всю старую информацию, ничего не перезаписывать.

Ключевое слово (совпадение) и информация, которую я хочу добавить, останутся неизменными каждый раз, даже если другие данные из файла изменятся.

To make a summary:

data that will change (not interested)

...

empty spaces < DATA >B506JGHD (< DATA > it would be the keyword(match) and i want to add for example 00000001 after it)

output that I need:empty spaces< DATA >00000001B506JGHD

...

empty spaces< DATA >J6443MNF

output:empty spaces< DATA >00000002J6443MNF

...


empty spaces< DATA >C89583F

output:empty spaces< DATA >00000003C89583F

...
other data (not interested)  

и так далее, в файле будет 7 ‹ DATA ›, поэтому я хочу добавить от 00000000 до 00000006 для каждого ‹ DATA ›.

Я ищу простое решение, если оно существует, я знаю, что мне, вероятно, нужно прочитать и просмотреть текстовый файл, найти ключевое слово и переписать все, но я не уверен, как это сделать.

What I tried so far is this:

use strict;
use warnings;

open FILE, "<FL_85E920795_Y060_H21_V001_E.odx" or die $!;
my @lines = < FILE >;
close FILE or die $!;

my $idx = 0;
my $string = '00000000';
do {
    if($lines[$idx] =~ /< DATA >/) 
        {
            splice @lines, $idx, 0, $string++;
            $idx++;
        }
    $idx++;
    } until($idx >= @lines);

open FILE, ">FL_85E920795_Y060_H21_V001_E.odx" or die $!;
print FILE join("",@lines);
close FILE;

но мне это не очень помогает, так как мой вывод выглядит следующим образом: 00000000 пустых мест ‹ DATA › Информация, если я попытаюсь переместить нужные мне данные перед ‹ DATA ›, он перезапишет все.

Первый ответ, который будет работать для меня, я приму как решение. Большое тебе спасибо


person Andrew    schedule 10.09.2020    source источник


Ответы (2)


#!/usr/bin/perl

use strict;
use warnings;

my $counter = "00000000";
while (<>) {
   s{< DATA >\K}{ $counter++ }eg;
   print;
}

Использование:

fn=FL_85E920795_Y060_H21_V001_E.odx
the_script "$fn" >"$fn".new
mv "$fn".new "$fn"

\K сохраняет то, что было сопоставлено с \K, и, таким образом, заменяет только пустую строку, следующую за < DATA >, значением, возвращаемым выражением замены.


Как однострочный:

perl -i -pe'BEGIN { $c = "00000000" }  s{< DATA >\K}{ $c++ }eg' \
   FL_85E920795_Y060_H21_V001_E.odx
person ikegami    schedule 10.09.2020
comment
Может я не правильно понял, пробовал: use strict; использовать предупреждения; мой $filename = 'FL_85E920795_Y060_H21_V001_E.odx'; открыть(FH, '‹', $filename) или умереть $!; мой счетчик $ = 00000000; в то время как (‹›) { s{‹ ДАННЫЕ ›\K}{ $counter++ }например; Распечатать; } закрыть(FH); Но это только копирует текст снова, ничего не добавляя. Если я использую › вместо ‹ при открытии файла, файл будет пустым, и вся информация будет перезаписана. Спасибо. - person Andrew; 10.09.2020

Желаемый результат может быть достигнут с помощью следующего демонстрационного кода

ПРИМЕЧАНИЕ:

  • это решение считывает весь файл в память
  • если файл слишком большой, предпочтительный подход будет читаться построчно
use strict;
use warnings;
use feature 'say';

my $count = 0;
my $re_match = qr/< DATA >/;

my $data = do { local $/; <DATA> };

$data =~ s/$re_match/sprintf "%08d",$count++/ge;

say $data;

__DATA__
To make a summary:

data that will change (not interested)

...

empty spaces < DATA >B506JGHD (< DATA > it would be the keyword(match) and i want to add for example 00000001 after it)

output that I need:empty spaces< DATA >00000001B506JGHD

...

empty spaces< DATA >J6443MNF

output:empty spaces< DATA >00000002J6443MNF

...


empty spaces< DATA >C89583F

output:empty spaces< DATA >00000003C89583F

...
other data (not interested) 

Выход

To make a summary:

data that will change (not interested)

...

empty spaces 00000000B506JGHD (00000001 it would be the keyword(match) and i want to add for example 00000001 after it)

output that I need:empty spaces0000000200000001B506JGHD

...

empty spaces00000003J6443MNF

output:empty spaces0000000400000002J6443MNF

...


empty spaces00000005C89583F

output:empty spaces0000000600000003C89583F

...
other data (not interested)
person Polar Bear    schedule 10.09.2020
comment
Ikegami предлагает более элегантное решение, когда $counter присваивается значение 00000000, что позволяет использовать $count++ вместо sprintf "%08d", $cont++ для подстановочной операции. - person Polar Bear; 10.09.2020
comment
Это удаляет < DATA > и добавляет конечную пустую строку. - person ikegami; 10.09.2020