FixFitid.pl
From GnuCash
#!/usr/bin/perl # # A quick script to fix non unique FITID ids in HSBC ofx downloads # makes a new unique id from the other details, so should match # a new overlapping download on a later date. # # usage: # FixFitid.pl bad_file.ofx > new_file.ofx # # It writes to std out, do pipe the output somewhere. use strict; use warnings; use Data::Dumper; exit main(@ARGV); our %seen_md5; BEGIN {$/="</STMTTRN>"} sub main{ while (my $frag = <>) { my $href = parseDetails($frag); my $md5 = genMD5($href); $frag = editFITID($frag,$md5); print $frag; } } sub parseDetails{ my $fragment = shift; my %ret; foreach my $part (qw(TRNTYPE DTPOSTED TRNAMT NAME MEMO FITID)){ if ($fragment =~ /<$part>(.*)<\/$part>/ ) { $ret{$part} = $1; } else { $ret{$part} = ""; next if $part eq "MEMO"; print STDERR "Failed to find $part in '$fragment'"; } } $ret{DTPOSTED} =~ s/^(\d{8}).*/$1/; return \%ret; } sub genMD5{ my $href = shift; my $string = join(" # ",@$href{qw(TRNTYPE DTPOSTED TRNAMT NAME MEMO)}); my $md5 = `echo '$string' | md5sum`; $md5 =~ s/^(\S+).*/$1/s; while ($seen_md5{$md5}){ $md5 = `echo '$md5' | md5sum`; $md5 =~ s/^(\S+).*/$1/s; #Handle multiple purchases with identical info. print STDERR "Duplicate MD5. Same transaction on same day. Progressing MD5 to $md5"; } $seen_md5{$md5}++; return $md5; } sub editFITID{ my $fragment = shift; my $md5 = shift; $fragment =~ s/<FITID>.*<\/FITID>/<FITID>$md5<\/FITID>/; return $fragment }