Pergunta

Eu tenho um diretório cheio de arquivos e eu preciso puxar os cabeçalhos e rodapés fora deles. Eles são todos comprimento variável para usar a cabeça ou cauda não está indo para o trabalho. Cada arquivo tem uma linha que eu posso procurar, mas eu não quero incluir a linha nos resultados.

É geralmente

*** Start (more text here)

e termina com

*** Finish (more text here)

Eu quero que os nomes de arquivo para permanecer o mesmo, então eu preciso para substituir os originais, ou escreva para um diretório diferente e eu vou substituí-los eu mesmo.

Oh sim, é em um servidor Linux é claro, então eu tenho Perl, sed, awk, grep, etc.

Foi útil?

Solução

Tente o flop aleta! ".." operador.

# 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 pode usar o interruptor perl -i para atualizar o arquivo (s) como assim .....

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

... que muda data.txt mas faz uma cópia de antemão como "copy_data.txt".

Outras dicas

coreutils GNU são seu amigo ...

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

Isso produz o arquivo desejado como xx00. Você pode alterar esse comportamento através do --prefix opções, --suffix e --digits, mas veja a manual para si mesmo. Desde csplit é projetado para produzir uma série de arquivos, não é possível produzir um arquivo sem sufixo, assim você terá que fazer o substituir manualmente ou através de um script:

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

Adicionar loops de como você deseja.

Para obter o cabeçalho :

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

Para obter o rodapé :

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

Para obter o arquivo de cabeçalho para rodapé como você quer:

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

Há mais de uma maneira, com o comando csplit, você deve tentar algo como:

csplit yourFileHere /Start/ /Finish/

E examinar arquivos chamados 'xxNN', onde NN está funcionando número, também dar uma olhada em csplit manpage .

Talvez? Início ao fim com não-exclusão.

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

ou ... menos certeza disso ... mas, se ele funciona, deve remover as linhas de início e término, bem como:

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

d! pode depender da largura do sed você tem - não tenho certeza
. E, eu escrevi que a memória inteiramente em (provavelmente pobres).

Um hack Perl rápida, não testada. Eu sou o suficiente para não fluente em sed ou awk para obter este efeito com eles, mas eu estaria interessado em como isso seria feito.

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

Alguns dos exemplos em perlfaq5: Como faço para alterar, excluir ou inserir uma linha em um arquivo ou acréscimo para o início de um arquivo? pode ajudar. Você vai ter que adaptá-las à sua situação. Além disso, a resposta do operador flip-flop de Leon é a maneira idiomática de fazer isso em Perl, embora você não tem que modificar o arquivo no lugar de usá-lo.

A Perl solução que substitui o arquivo original.

#!/usr/bin/perl -ni
if(my $num = /^\*\*\* Start/ .. /^\*\*\* Finish/) {
    print if $num != 1 and $num + 0 eq $num;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top