sexta-feira, 24 de outubro de 2008

Bash Script: Convertendo vcf para txt (vcf2txt 0.2)

Certo dia estava precisando converter arquivos VSF (formato utilizado para troca de contatos entre programas e mesmo entre dispositivos) em arquivos TXT e acabei por escrever o script abaixo. Eu diria que o mesmo se encontra em uma versão beta, pois ainda não possui todas as funcionalidades que eu gostaria que ele tivesse, mas fica ai como uma primeira versão e mesmo como um gancho para outras criações.

Um detalhe importante, é preciso antes de executar o mesmo, modificar as variáveis ARQUIVOENTRADA, ARQUIVOSAIDA e ARQUIVOSAIDATAB, inserindo nos locais indicados o nome dos arquivos de entrada e de saída. Ah sim, também é importante não esquecer de ao salvar o script mudar a sua permissão para permitir execução :D

Para baixar o arquivo diretamente para sua máquina, acesse o endereço: http://hailtales.googlepages.com/vsf2txt.sh.gz

#!/bin/bash

# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# EDITE AQUI

# ARQUIVO VSF ENTRADA
ARQUIVOENTRADA="/home/usuario/entrada.vcf"

# ARQUIVO DE SAIDA SIMPLES
ARQUIVOSAIDA="/home/usuario/saida.txt"

# ARQUIVO DE SAIDA TABULADO
ARQUIVOSAIDATAB="/home/usuario/saida.tab"

# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

########################################
# VSF 2 TXT
# por Tales de Azevedo - 23/03/2008
# hailtales@gmail.com
# http://hailtales.blogspot.com
#
# Este programa é software livre; você pode redistribui-lo e/ou modificá-lo sob
# os termos da Licença Pública Geral GNU, conforme publicada pela Free Software
# Foundation; tanto a versço 2 da Licença como (a seu critério) qualquer versão
# mais actual.
#
# Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
# GARANTIA; incluindo as garantias implícitas de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
# A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
# obter mais detalhes.
########################################

INICIO=0
SEPARADOR=":::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
# caso já exista um arquivo de saída, ele será sobrescrito
rm ${ARQUIVOSAIDA}

# funcao que evita a impressao de lixo nos logs de saida
ZERAVAR()
{

NOME=" "
CEL=" "
CASA=" "
TRAMPO=" "
EMAIL=" "
ANI=" "

}

# log da saida normal
LOGSAIDA()
{

# Escreve o arquivo de saída
echo ${NOME} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "\t\t" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${CEL} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "\t" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${CASA} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "\t" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${TRAMPO} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "\t" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${EMAIL} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "\t" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${ANI} | tr -s '[:cntrl:]' ' ' >> ${ARQUIVOSAIDA}
printf "\n" >> ${ARQUIVOSAIDA}

}

# log de saida tabelado
LOGSAIDATAB()
{

# Escreve o arquivo de saída
echo ${NOME} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDATAB}
printf ":" >> ${ARQUIVOSAIDATAB}

# Escreve o arquivo de saída
echo ${CEL} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDATAB}
printf ":" >> ${ARQUIVOSAIDATAB}

# Escreve o arquivo de saída
echo ${CASA} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDATAB}
printf ":" >> ${ARQUIVOSAIDATAB}

# Escreve o arquivo de saída
echo ${TRAMPO} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDATAB}
printf ":" >> ${ARQUIVOSAIDATAB}

# Escreve o arquivo de saída
echo ${EMAIL} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDATAB}
printf ":" >> ${ARQUIVOSAIDATAB}

# Escreve o arquivo de saída
echo ${ANI} | tr -s '[:cntrl:]' ' ' >> ${ARQUIVOSAIDATAB}
printf "\n" >> ${ARQUIVOSAIDATAB}

}


clear
export INICIO



# lendo arquivo entrada
cat ${ARQUIVOENTRADA} |
while read CAMPO
do
if [[ "${CAMPO}" =~ "BEGIN" ]]
then
# Define o inicio de um registro
INICIO=1
ZERAVAR
echo "${SEPARADOR}"
elif [[ "${CAMPO}" =~ "END" ]]
then
# Define o fim de um registro
INICIO=0
LOGSAIDATAB
LOGSAIDA
elif [ "${INICIO}" -eq "1" ]
then
# Procura pelo campo nome do contato (name)
if [[ "${CAMPO}" =~ "N:" ]]
then
# Essa rotina garante que nome (name) nao sera confundido com versao
if [[ "${CAMPO}" =~ "VERSION:" ]]
then
:
else
NOME=`echo ${CAMPO}|cut -d : -f 2 | cut -d ";" -f 2`
echo ${NOME}
fi
# Procurando pelo endereco (address)
elif [[ "${CAMPO}" =~ "ADR;" ]]
then
ENDERECO=`echo ${CAMPO}|cut -d : -f 2 | tr ";" " " `
echo "O endereço é ${ENDERECO}"
# Procurando os numeros de telefone (phone numbers) e separando em categorias
elif [[ "${CAMPO}" =~ "TEL;" ]]
then
if [[ "${CAMPO}" =~ "CELL" ]]
then
CEL=`echo ${CAMPO}|cut -d : -f 2`
echo "O telefone celular é ${CEL}"
elif [[ "${CAMPO}" =~ "HOME" ]]
then
CASA=`echo ${CAMPO}|cut -d : -f 2`
echo "O telefone residencial é ${CASA}"
elif [[ "${CAMPO}" =~ "WORK" ]]
then
TRAMPO=`echo ${CAMPO}|cut -d : -f 2`
echo "O telefone profissional é ${TRAMPO}"
else
TOUTRO=`echo ${CAMPO}|cut -d : -f 2`
echo "Outro telefone: ${TOUTRO}"
fi
# Procurando pelo endereco de correio eletronico (e-mail)
elif [[ "${CAMPO}" =~ "EMAIL;" ]]
then
EMAIL=`echo ${CAMPO}|cut -d : -f 2`
echo "O e-mail é ${EMAIL}"
# Caso o contato possua um site
elif [[ "${CAMPO}" =~ "URL;" ]]
then
echo "O site é ${CAMPO}"
# Aniversario do contato (birthday)
elif [[ "${CAMPO}" =~ "BDAY:" ]]
then
ANI=`echo ${CAMPO}|cut -d : -f 2`
echo "O aniversário é ${ANI}"
else
:
fi
else
:
fi
done

Atualizado:
Eis abaixo a versão 0.2 do script de conversão de arquivos vcf para txt escrito em shell script. Basicamente as mudanças nessa versão são:
  • Função unificada para geração do arquivo de saída;
  • Função de organização da saída;
  • Reconhecimento de nomes com especificação de charset;
  • Reconhecimento do campo de sobrenome;

Para baixar o arquivo basta clicar aqui.

Abaixo o código para consulta:

#!/bin/bash

# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# EDITE AQUI

# ARQUIVO VSF ENTRADA
ARQUIVOENTRADA="/home/tales/All.vcf"

# ARQUIVO DE SAIDA
ARQUIVOSAIDA="/home/tales/saida.txt"

# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

########################################
# VSF 2 TXT
# por Tales de Azevedo - 23/03/2008
# hailtales@gmail.com
# http://hailtales.blogspot.com
#
# Este programa é software livre; você pode redistribui-lo e/ou modificá-lo sob
# os termos da Licença Pública Geral GNU, conforme publicada pela Free Software
# Foundation; tanto a versço 2 da Licença como (a seu critério) qualquer versão
# mais actual.
#
# Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
# GARANTIA; incluindo as garantias implícitas de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
# A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
# obter mais detalhes.
########################################

INICIO=0
SEPARADOR=":::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
# caso já exista um arquivo de saída, ele será sobrescrito
rm ${ARQUIVOSAIDA}

# funcao que evita a impressao de lixo nos logs de saida
ZERAVAR()
{

NOME=" "
CEL=" "
CASA=" "
TRAMPO=" "
EMAIL=" "
ANI=" "

}
LOGSAIDA()
{
#TAB=\t
TAB=":"
TABFIM=\n
# Escreve o arquivo de saída
echo ${NOME} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "${TAB}${TAB}" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${CEL} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "${TAB}" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${CASA} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "${TAB}" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${TRAMPO} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "${TAB}" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${EMAIL} | tr -s '[:cntrl:]' '\000' >> ${ARQUIVOSAIDA}
printf "${TAB}" >> ${ARQUIVOSAIDA}

# Escreve o arquivo de saída
echo ${ANI} | tr -s '[:cntrl:]' ' ' >> ${ARQUIVOSAIDA}
printf "\n" >> ${ARQUIVOSAIDA}

}

ORGANIZA()
{
# Organiza o arquivo final em ordem alfabética
mv ${ARQUIVOSAIDA} ${ARQUIVOSAIDA}.tmp
sort ${ARQUIVOSAIDA}.tmp > ${ARQUIVOSAIDA}

}

clear
export INICIO



# lendo arquivo entrada
cat ${ARQUIVOENTRADA} |
while read CAMPO
do
#echo "DEBUG - CAMPO = $CAMPO"
if [[ "${CAMPO}" =~ "BEGIN" ]]
then
# Define o inicio de um registro
INICIO=1
ZERAVAR
echo "${SEPARADOR}"
elif [[ "${CAMPO}" =~ "END" ]]
then
# Define o fim de um registro
INICIO=0
LOGSAIDA
elif [ "${INICIO}" -eq "1" ]
then
# Procura pelo campo nome do contato (name)
if [[ "${CAMPO}" =~ "N:" ]]
then
# Essa rotina garante que nome (name) nao sera confundido com versao
if [[ "${CAMPO}" =~ "VERSION:" ]]
then
:
else
NOME=`echo ${CAMPO}|cut -d : -f 2 | cut -d ";" -f 2`
SNOME=`echo ${CAMPO}|cut -d : -f 2 | cut -d ";" -f 1`
NOME="${NOME} ${SNOME}"
echo ${NOME}
fi
# Procurando pelo nome com charset (name)
elif [[ "${CAMPO}" =~ "N;CHARSET=ISO-8859-1:" ]]
then
NOME=`echo ${CAMPO}|cut -d : -f 2 | tr ";" " " `
echo "${NOME}"
# Procurando pelo endereco (address)
elif [[ "${CAMPO}" =~ "ADR;" ]]
then
ENDERECO=`echo ${CAMPO}|cut -d : -f 2 | tr ";" " " `
echo "O endereço é ${ENDERECO}"
# Procurando os numeros de telefone (phone numbers) e separando em categorias
elif [[ "${CAMPO}" =~ "TEL;" ]]
then
if [[ "${CAMPO}" =~ "CELL" ]]
then
CEL=`echo ${CAMPO}|cut -d : -f 2`
echo "O telefone celular é ${CEL}"
elif [[ "${CAMPO}" =~ "HOME" ]]
then
CASA=`echo ${CAMPO}|cut -d : -f 2`
echo "O telefone residencial é ${CASA}"
elif [[ "${CAMPO}" =~ "WORK" ]]
then
TRAMPO=`echo ${CAMPO}|cut -d : -f 2`
echo "O telefone profissional é ${TRAMPO}"
else
TOUTRO=`echo ${CAMPO}|cut -d : -f 2`
echo "Outro telefone: ${TOUTRO}"
fi
# Procurando pelo endereco de correio eletronico (e-mail)
elif [[ "${CAMPO}" =~ "EMAIL;" ]]
then
EMAIL=`echo ${CAMPO}|cut -d : -f 2`
echo "O e-mail é ${EMAIL}"
# Caso o contato possua um site
elif [[ "${CAMPO}" =~ "URL;" ]]
then
echo "O site é ${CAMPO}"
# Aniversario do contato (birthday)
elif [[ "${CAMPO}" =~ "BDAY:" ]]
then
ANI=`echo ${CAMPO}|cut -d : -f 2`
echo "O aniversário é ${ANI}"
else
:
fi
else
:
fi
done
ORGANIZA

2 comentários:

Rafael disse...

Nenhum dos 2 funciona.

Tales de Azevedo disse...

Rafael,
provavelmente os arquivos VSF que você tentou converter possuem campos diferentes dos que eu utilizei nesses scripts. Não me recordo o por quê de tê-los escrito, mas acho que era para o meu falecido Palm Zire 71