Как я могу извлечь строки текста из файла? - PullRequest
2 голосов
/ 17 ноября 2008

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

Обычно

*** Start (more text here)

И заканчивается

*** Finish (more text here)

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

О да, конечно, на сервере Linux, поэтому у меня есть Perl, sed, awk, grep и т. Д.

Ответы [ 7 ]

3 голосов
/ 17 ноября 2008

Попробуйте оператор триггер!"..".

# flip-flop.pl
use strict;
use warnings;

my $start  = qr/^\*\*\* Start/;
my $finish = qr/^\*\*\* Finish/;

while ( <> ) {
    if ( /$start/ .. /$finish/ ) {
        next  if /$start/ or /$finish/;
        print $_;
    }
}

U может затем использовать ключ -i perl для обновления ваших файлов следующим образом .....

 $ perl -i'copy_*' flip-flop.pl data.txt 

... который изменяет data.txt, но предварительно делает копию как "copy_data.txt".

2 голосов
/ 18 ноября 2008

GNU coreutils - ваш друг ...

csplit inputfile %^\*\*\* Start%1 /^\*\*\* Finish/ %% {*}

Создает нужный файл как xx00. Вы можете изменить это поведение с помощью опций --prefix, --suffix и --digits, но посмотрите руководство для себя. Поскольку csplit предназначен для создания нескольких файлов, невозможно создать файл без суффикса, поэтому вам придется выполнить перезапись вручную или с помощью сценария:

csplit $1 %^\*\*\* Start%1 /^\*\*\* Finish/ %% {*}
mv -f xx00 $1

Добавляйте циклы по своему желанию.

1 голос
/ 17 ноября 2008

Чтобы получить заголовок :

cat yourFileHere | awk '{if (d > 0) print $0} /.*Start.*/ {d = 1}'

Чтобы получить нижний колонтитул :

cat yourFileHere | awk '/.*Finish.*/ {d = 1} {if (d < 1) print $0}'

Чтобы получить файл из заголовка в нижний колонтитул , как вы хотите:

cat yourFileHere | awk '/.*Start.*/ {d = 1; next} /.*Finish.*/ {d = 0; next} {if (d > 0) print $0}'

Есть еще один способ, с помощью команды csplit, вы должны попробовать что-то вроде:

csplit yourFileHere /Start/ /Finish/

И просмотрите файлы с именем 'xxNN', где NN - это порядковый номер, также посмотрите на csplit manpage .

0 голосов
/ 18 ноября 2008

Некоторые примеры в perlfaq5: Как мне изменить, удалить или вставить строку в файл или добавить в начало файла? может помочь. Вам придется адаптировать их к вашей ситуации. Кроме того, ответ оператора триггера Леона - идиоматический способ сделать это в Perl, хотя вам не нужно изменять файл на месте, чтобы использовать его.

0 голосов
/ 17 ноября 2008

Решение Perl, которое перезаписывает исходный файл.

#!/usr/bin/perl -ni
if(my $num = /^\*\*\* Start/ .. /^\*\*\* Finish/) {
    print if $num != 1 and $num + 0 eq $num;
}
0 голосов
/ 17 ноября 2008

Быстрый взлом Perl, не тестировался. Я не достаточно свободно говорю в sed или awk, чтобы получить с ними этот эффект, но мне было бы интересно узнать, как это будет сделано.

#!/usr/bin/perl -w
use strict;
use Tie::File;
my $Filename=shift;  
tie my @File, 'Tie::File', $Filename or die "could not access $Filename.\n";  
while (shift @File !~ /^\*\*\* Start/) {};  
while (pop @File !~ /^\*\*\* Finish/) {};  
untie @File;  
0 голосов
/ 17 ноября 2008

Может быть? Начните до конца, не удаляя.

$ sed -i '/^\*\*\* Start/,/^\*\*\* Finish/d!' *

или ... менее уверен в этом ... но, если он работает, следует удалить также строки начала и окончания:

$ sed -i -e '/./,/^\*\*\* Start/d' -e '/^\*\*\* Finish/,/./d' *

d! может зависеть от сборки sed у вас - не уверен.
И я написал это полностью (вероятно, плохо) памяти.

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