Como dividir um arquivo usando limites de palavra-chave

11

Eu tenho um arquivo vcf que contém vários vcards.

Ao importar o arquivo vcf para o outlook, parece importar apenas o primeiro vcard.

Por isso, quero dividi-los.

Dado que um vcard começa com

BEGIN:VCARD

e termina com

END:VCARD

Qual é a melhor maneira de dividir cada vcard em seu próprio arquivo?

Obrigado

UPDATE

Obrigado por todas as respostas. Tal como acontece com questões desta natureza, existem várias maneiras de esfolar um gato. Aqui está o raciocínio porque escolhi o que fiz.

ROUND-UP

Aqui está um resumo do que eu gostei de cada resposta e o que me levou a escolher uma delas.

  • csplit : Gostei muito da concisão deste método. Eu só queria poder definir a extensão do arquivo.
  • gawk : Ele fez tudo o que eu pedi.
  • paralell : trabalhado. Mas eu tive que instalar coisas novas. (também decidiu criar um novo diretório / bin no meu diretório home)
  • perl : Gostei que tenha criado o vcf com base no nome do contato. Mas a opção -o não funcionou realmente

Conclusão

  • Então o primeiro a ir foi perl porque estava um pouco quebrado
  • O próximo foi paralell porque tive que instalar coisas novas
  • O próximo foi csplit , porque, até onde eu posso ver, ele não pode criar extensões nos arquivos de saída
  • Então o prêmio vai para o gawk, por ser um utilitário que está prontamente disponível e versátil o suficiente para que eu possa cortar e alterar o nome do arquivo um pouco. Marcas de bônus por cmp também:)
por denormalizer 24.05.2013 / 10:11

5 respostas

10

Você pode usar o awk para o trabalho:

$ curl -o example.vcf http://qt.gitorious.org/qt-mobility/contacts/blobs/raw/\
d7f10927176b8c3603efaaceb721b00af5e8605b/demos/qmlcontacts/contents/example.vcf

$ gawk ' /BEGIN:VCARD/ { ++a; fn=sprintf("card_%02d.vcf", a); 
        print "Writing: ", fn } { print $0 >> fn; } ' example.vcf
Writing:  card_01.vcf
Writing:  card_02.vcf
Writing:  card_03.vcf
Writing:  card_04.vcf
Writing:  card_05.vcf
Writing:  card_06.vcf
Writing:  card_07.vcf
Writing:  card_08.vcf
Writing:  card_09.vcf

$ cat card_0* > all.vcf
$ cmp example.vcf all.vcf
$ echo $?
0

Detalhes

A linha awk funciona assim: a é o contador que é incrementado em cada linha BEGIN:VCARD e ao mesmo tempo o nome do arquivo de saída é construído usando sprintf (armazenado em fn ). Para cada linha, a linha atual ( $0 ) é anexada ( >> ) ao arquivo atual (denominado fn ).

O último echo $? significa que o cmp foi bem-sucedido, ou seja, todos os arquivos individuais concatenados são iguais ao exemplo original do vcf.

Observe que a linha awk assume que você não possui arquivos com o nome card_[0-9][0-9].vcf em seu diretório de trabalho atual. Você também pode substituí-lo por algo como

$ gawk ' /BEGIN:VCARD/ { ++a; fn=sprintf("card_%02d.vcf", a);
          print "Writing: ", fn; print $0 > fn; next }
        { print $0 >> fn; } ' example.vcf

que sobrescreveria os arquivos existentes.

    
por 25.05.2013 / 14:56
9
csplit -f vcard input.txt -z '/END:VCARD/+1' '{*}'
    
por 25.05.2013 / 15:17
4

Você pode usar este script para fazer o trabalho. Chama-se split-vcf-file .

Exemplo de uso

$ split_vcf.pl 

Error! Input VCF filename missing,  -i

Usage: perl split_vcf.pl -i input_file -o output_dir [OPTION]

    -v,         Verbosity levels, 1-3

Para executar o script:

mkdir vcf_files
split_vcf.pl  -i current.vcf -o vcf_files
    
por 24.05.2013 / 10:20
4

Usando o GNU Parallel, você pode fazer:

cat foo.vcf | parallel --pipe -N1 --recstart BEGIN:VCARD 'cat >{#}'

Veja mais exemplos: link

Assista aos vídeos de introdução: link

10 segundos de instalação:

wget -O - pi.dk/3|sh
    
por 24.05.2013 / 13:27
4

csplit pode definir a extensão - a resposta de Ignacio, eu acho que é a mais concisa, só precisa do último bit de ajustes para obter a extensão - usando o formato 'printf':

csplit -f vcard -b %02d.vcard input.txt -z '/END:VCARD/+1' '{*}'

Este é o snippet relevante da página csplit man:

   -b, --suffix-format=FORMAT
          use sprintf FORMAT instead of %02d
    
por 13.11.2013 / 16:34

Tags