Прочитайте файл и измените его - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь обработать поток данных.

Сначала я добавляю текстовый файл в свой скрипт.

Текстовый файл выглядит так:

pierwsza linia  koniec
druga linia lorem1 koniec lorem1 lorem1
trzecia linia lorem1 koniec lorem1
czwarta linia lorem1 koniec
piata liniakoniec
szosta linia lorem1 koniec

Я хочу получить файл со всеми строками, но с первым появлением lorem1.

поэтому ожидаемый результат должен быть таким:

pierwsza linia  koniec
druga linia lorem1 koniec
trzecia linia koniec
czwarta linia koniec
piata liniakoniec
szosta linia koniec

Мой сценарий выглядит так

#!/usr/bin/perl -pi

use strict;

my $line = $_;
my $loremcn;

while ( $line = <> ) {

    #if ( $line =~ m/lorem1/ )

    foreach ( $line =~ m/lorem1/gi ) {

        $loremcn++;

        if ( $loremcn >= 2 ) {
            $line =~ s/lorem1//gi;
        }

        print "$loremcn\n";
        print $line;

        chomp $line;
    }
}

Однако результат - только одна, первая строка (из-за -pi в начале скрипта) текста.

Скрипт правильно подсчитывает вхождения lorem1 (7), но из-за опции /g он удаляет все lorem1 вхождения (не оставляет первого в покое).

Наконец, как в конце вывести весь исправленный текст на экран?

Обновление

Я написал этот важный комментарий к одному из ответов:

В РЛ я не могу сделать это по-своему. Весь этот тренинг состоит в том, чтобы найти способ сделать это с потоковыми данными. В истинном сценарии все данные не из открытого текста, а данные из буфера, передаваемые на принтер из SAP. И эти данные необходимо исправить на пути к принтеру

Ответы [ 4 ]

0 голосов
/ 04 сентября 2018

Один лайнер с использованием perl:

Вы можете сохранить все до первого лорема, а затем удалить все лоремы, т. Е.

 $perl -pe "undef $/;s/^.*?\blorem1\K|\blorem1//g" lorem.txt
  • \b - используется для определения границы.
  • .*? - не жадный матч. все соответствует второму lorem
  • \K - отменить все ранее использованные символы. Таким образом, удалив от второго до конца

выход

pierwsza linia  koniec
druga linia lorem1 koniec
trzecia linia  koniec
czwarta linia  koniec
piata liniakoniec
szosta linia  koniec

Теперь, если вы хотите сохранить это в другом файле, вы можете сделать:

perl -pe "undef $/;s/^.*?\blorem1\K|\blorem1//g" lorem.txt > new_file.txt

Если ваша версия perl не поддерживает \K, вы можете использовать:

 perl -pe "undef $/;s/(^.*?\blorem1)|\blorem1/$1/g" lorem.txt
0 голосов
/ 03 сентября 2018

Разве это не только это?

my $seen;
while (<>) {
  s/\blorem1\b//g if $seen;
  $seen = 1 if /\blorem1\b/;
  print;
}

Обновление: Хорошо, это немного сложнее, чем я думал. Но это похоже на то, что вы хотели:

#!/usr/bin/perl

use strict;
use warnings;

my $seen;

while (<>) {
  if ($seen) {
    s/\blorem1\b//g;
  } else {
    1 while s/(?<=\blorem1\b)(.*)\blorem1\b/$1/g;
    $seen = 1 if /\blorem1\b/;
  }
  print;
}
0 голосов
/ 03 сентября 2018

Запуск вашего кода с B::Deparse вот так

perl -MO=Deparse xx.pl

дает этот результат

BEGIN { $^I = ""; }   # From -i

LINE: while (defined($_ = readline ARGV)) {


    use strict;
    my $line = $_;
    my $loremcn;
    while (defined($line = readline ARGV)) {
        foreach $_ ($line =~ /lorem1/gi) {
            ++$loremcn;
            if ($loremcn >= 2) {
                $line =~ s/lorem1//gi;
            }
            print "$loremcn\n";
            print $line;
            chomp $line;
        }
    }


}
continue {
    die "-p destination: $!\n" unless print $_;
}

Итак, вы видите, что в вашем коде есть два while цикла: вам не следует смешивать параметры командной строки с программным файлом, поскольку результат может быть неочевидным

Вот способ сделать то, что я думаю вы хотите. Он использует ваш глобальный счетчик $loremcn вместе с выражением глобальной замены, чтобы заменить lorem1 ничем после первого экземпляра

#!/usr/bin/perl

use strict;
use warnings 'all';

@ARGV = 'file1.txt';

my $loremcn = 0;

while ( <> ) {

    s{(\blorem1\b[ \t]*)}{ $loremcn++ ? '' : $1 }ge;

    print;
}
* * Выход тысяча двадцать-один * * одна тысяча двадцать-дв
pierwsza linia  koniec
druga linia lorem1 koniec 
trzecia linia koniec 
czwarta linia koniec
piata liniakoniec
szosta linia koniec
0 голосов
/ 03 сентября 2018
#!/usr/bin/perl 
use strict;
use warnings;

# lorem counter
my $loremcn = 0;
# loop over the input file
while (my $line = <> ) {
    # if line contains lorem1 but not alorem1 or lorem12
    if ($line =~ /\blorem1\b/i) {
        # not the first time. counter > 0
        if ($loremcn) {
            # remove all lorem1 and optional leading horizontal spaces
            $line =~ s/\h*\blorem1\b//gi;   # comment for syntax color /
        # first time lorem1 is encountered (counter == 0)
        } else {
            # remove all lorem1 but the first
        while ($line =~ s/
                            (\blorem1\b.*?)     # first lorem1 in the line followed by 0 or more anycharacter
                            \blorem1\b          # subsequent lorem1
                            /$1/gix             # replace with the first group (i.e. the first lorem1
            ) { 1;}
        }
        # incement counter
        $loremcn++;
    }
    # print the modified line
    print $line;
}

Выход:

pierwsza linia  koniec
druga linia lorem1 koniec  
trzecia linia koniec
czwarta linia koniec
piata liniakoniec
szosta linia koniec

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

perl test.pl inputfile > outputfile
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...