Created
July 21, 2009 05:29
-
-
Save jonjensen/151139 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# Gmail notes converter | |
# by Jon Jensen <[email protected]> | |
# 2009-07-20 | |
# Copyright 2009 Jon Jensen. Distributed under the GPLv3 license. | |
# For details see http://www.gnu.org/licenses/gpl-3.0.html | |
# When importing e.g. Nokia phone contacts into Gmail, most fields are | |
# crammed into a single Notes field that is useless in the Android phone | |
# contacts feature. This script takes Gmail-exported contacts in CSV | |
# (comma-separated values) format and converts those notes into regular | |
# phone contact entries, which can then be imported back into Gmail. | |
# Usage: | |
# ./gmail-notes-converter input.csv > output.csv | |
use 5.006; use 5.10.0; | |
use strict; | |
use warnings; | |
my %note2description = ( | |
Business => 'Work', | |
General => 'Personal', | |
Home => 'Personal', | |
); | |
undef $/; | |
my $file = <>; | |
my @lines; | |
# yes, could use Text::CSV, but this works and has no dependencies | |
while (length($file)) { | |
my @fields; | |
# all but final field of row | |
while ( | |
$file =~ s{ | |
\A | |
(?: | |
"([^"]*)" | |
| | |
([^,\r\n]*) | |
) | |
, | |
}{}xg | |
) { | |
push @fields, $1 // $2; | |
} | |
# final field of row | |
if ( | |
$file =~ s{ | |
\A | |
(?: | |
"([^"]*)" | |
| | |
([^\r\n]*) | |
) | |
\r?\n | |
}{}x | |
) { | |
push @fields, $1 // $2; | |
} | |
push @lines, \@fields; | |
} | |
my @header = @{ shift @lines }; | |
my %header2column; | |
{ | |
my $i = 0; | |
$header2column{$_} = $i++ for @header; | |
} | |
for my $line (@lines) { | |
my %description2number; | |
my @number; | |
my %field; | |
my $i = 0; | |
for (@$line) { | |
$field{$header[$i]} = $_ // ''; | |
if ($_ and $header[$i] =~ /^Section (\d+) - Description$/) { | |
$description2number{$_} = $1; | |
$number[$1 - 1] = $_; | |
} | |
++$i; | |
} | |
for (qw( Work Personal Other )) { | |
next if defined $description2number{$_}; | |
push @number, $_; | |
my $number = scalar @number; | |
$description2number{$_} = $number; | |
$field{"Section $number - Description"} = $_; | |
} | |
if (my $notes = delete $field{Notes}) { | |
for my $note (split /\s*\r?\n\s*/, $notes) { | |
my ($cat, $type, $value) = ($note =~ /^(\w+)\s+(\w+):\s+(.*)/); | |
my $title = "Section $description2number{$note2description{$cat}} - \u$type"; | |
warn(qq{$field{Name}: Ignoring note value "$value" that conflicts with existing value "$field{$title}"\n}), next | |
if $field{$title}; | |
$field{$title} = $value; | |
} | |
} | |
$line = [ map { $field{$_} } @header ]; | |
} | |
{ | |
no warnings 'uninitialized'; | |
for my $line (\@header, @lines) { | |
my $out = join(',', map { /[,\n\r"]/ ? qq{"$_"} : $_ } @$line); | |
# trim trailing empty fields to save space | |
$out =~ s/,+$//; | |
print $out, "\n"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment