logo

nixscript

Keep it simple, stupid !

Ссылка на статью в формате MarkDown для Curl, кодировка RU.UTF-8

Конвертер VCARD (VCF 3.0) ⧎ CSV

Адрес статьи: https://nixscript.ru/vcf2csv

На работе возникла задача привести в порядок адресную книгу E-Mail. Выгрузил в формате VCARD 3.0, понял, что проще застрелиться, чем пытаться вручную привести в порядок. Соответственно взялся за то, что под рукой. А под рукой всемогущий BASH. )))

Проблема усугублялась наличием большого количества абсолютных дублей адресов, так как адресную книгу слепил из трех книг от разных сотрудников. Но успокаивало то, что можно загнать всё в формат CSV, который открывается Экселем и LibreCalc, соответственно разгребать бардак можно не только мне.

Начнём с форматов.


VCF - формат VCARD 3.0.

Довольно простой текстовый формат, где данные поделены на отдельные строки и содержат в начале тег-описатель. Пример:

BEGIN:VCARD
VERSION:3.0
UID:XXXXXXXXXXX
EMAIL:email1@host.tld
EMAIL:email2@host.tld
EMAIL:email3@host.tld
FN:Имя Получателя
N:Подробная;Информация;5;Полей;Вроде бы
END:VCARD

И каждый контакт описывается таким набором строк.

CSV

Простейший формат хранения таблиц и массивов. Строки содержат значения полей таблиц, разделённые каким-либо символом-разделителем. Чаще всего, символ разделитель - точка с запятой. Но так как в формате VCARD этот разделитель задействован для разделения полей подробной информации, я выбрал символ табуляции, что вполне допустимо.

Переходим к скриптам


И так, скрипт первый. vcf2csv. С комментариями, чтобы не просто скопипастить, а подумать, понять и применять:

#!/bin/bash

# Делаем условие по ключу -2, которое
# выдаст первой строкой заголовки таблиц.
# Расчёт на то, чтобы можно было загнать
# в один CSV несколько VCF.
# В качестве разделителя полей выбрана табуляция.
if [[ $2 == "-1" ]]; then echo "UID     EMAIL   FN      N" | tr -d "\n"; fi

# Теперь идёт конвейер.
# * SED удаляет ненужное из строк и некоторые строки
# * tr удаляет перевод строки и возврат
#   корретки
# * SED вставляет перевод строки
#   в нужном месте, разделяя один контакт от
#   другого
# * SED обрабатывает поле адреса e-mail
# * SED всавляет разделителем адресов
#   точку с запятой
# * ... два раза, поскольку
#   адресов бывает три на один контакт
# * sort сортирует всё таким образом, чтобы
#   одинаковые строки шли друг за другом
# * uniq удаляет дубли, остовляя все строки в
    единственном экземпляре
sed -e '
/BEGIN:VCARD/d
s/VERSION:3.0/*/
s/UID://
s/EMAIL:/       EML:/
s/FN:/  /
s/N:/   /
/X-SOCIALPROFILE/d
/BDAY/d
/X-YA/d
/END:VCARD/d' "$1" | tr -d "\r\n" | sed "y/*/\n/" | sed "s/     EML:/   /1" | sed "s/   EML:/;/" | sed "s/  EML:/;/" | sort | uniq

Вызов производится таким образом:.

vcf2csv vcards.vcf -1 >vcards.csv
vcf2csv vcards1.vcf >>vcards.csv
vcf2csv vcards2.vcf >>vcards.csv

В этом примере три файла карточек объединяются в один CSV. Заметьте, первый вызов скрипта идёт с ключом -1. Этот ключ обязательно должен быть вторым аргументом. Иначе не будет работать правильно. Можно доделать, додумать, создать защиту от дурака, но оставлю это вам. )))

Скрипт второй. csv2vcf. Он вернёт обработанные и открректированные контакты в VCF для загрузки в почтовый клиент.

#!/bin/bash

# Получаем файл CSV первым аргументом и
# грузим в переменную
LIST=$(sed '1d' "$1")

# Указываем разделителем перевод
# строки, чтобы проедставить содержимое
# переменной LIST как массив для обработки
# в цикле.
IFS=$"
"

# Начинаем цикл, обрабатывающий каждую
# строку отдельно
for ROW in $LIST do
# Получаем первое поле, которое содержит UID
        U=$(echo "$ROW" | cut -d "      " -f1)

# Далее второе поле с адресами e-mail
        E=$(echo "$ROW" | cut -d "      " -f2)

# Теперь разделяем адреса на
отдельные строки
        EML="${E//;/\\r\\nEMAIL:}"

# Получаем текст представления адресата
        F=$(echo "$ROW" | cut -d "      " -f3)

# И подробную информацию о контакте,
# разделённую точкой с запятой
        N=$(echo "$ROW" | cut -d "      " -f4)

# Остаётся лишь выдать это в
# правильном, для формата VCF виде
        echo -e "BEGIN:VCARD\r\nVERSION:3.0\r\nUID:${U}\r\nEMAIL:${EML}\r\nFN:${F}\r\nN:${N}\r\nEND:VCARD"
done

Вызов делается проще чем с первым скриптом:

csv2vcf vcards.csv >vcarsd-result.vcf

Вот и всё. Относительно просто, мы экономим от двух дней до недели ковыряния в адресной книге клиента. В моём случае, это веб-клиент Яндекса.

Автор: Grigruss 24.04.2019


Статья написана в формате MarkDown и сконвертирована в HTML с помощью скрипта Parsedown.

Вверх 🡑