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

#perl #splice

#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 < ДАННЫХ > в файле, поэтому я хочу добавить 00000000 к 00000006 для каждого < ДАННЫЕ >.

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

 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 >, они перезапишут все.

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

Ответ №1:

 #!/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
  

Комментарии:

1. Возможно, я не правильно понял, я пытался: использовать строгий; использовать предупреждения; мой $filename = ‘FL_85E920795_Y060_H21_V001_E.odx’; открыть (FH, ‘<‘, $filename) или умереть $!; мой $counter = «00000000»; в то время как (<>) { s{< DATA > K}{ $counter },например; печать; } закрыть (FH); Но это только копирует текст снова, ничего не добавляя. Если я использую > вместо < при открытии файла, файл будет пустым, а вся информация будет перезаписана. Спасибо.

Ответ №2:

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

ПРИМЕЧАНИЕ:

  • это решение считывает весь файл в память целиком
  • если файл слишком большой, предпочтительным подходом было бы чтение построчно
 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 "d",$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)
  

Комментарии:

1. Ikegami предлагает более элегантное решение, когда $counter присваивается значение 00000000 , которое позволяет использовать $count вместо sprintf "d", $cont операции замены.

2. Это удаляет < DATA > и добавляет завершающую пустую строку