Parsing ADIF with Perl

In ham radio, we’re plagued with a data log standard called ADIF, the Amateur Data Interchange Format. It certainly is amateur, in the bad sense of the word. It looks like someone once saw SGML in a fever dream, and wrote down what little they remembered.

Anyway, the following Perl snippet will parse an ADIF file into an array of hashes. It was based on some code from PerlMonks that kinda worked. This works for all the file (singular) I tested.

#!/usr/bin/perl -w
# modified from perlmonks - TedPride - http://www.perlmonks.org/?node_id=559222
use strict;

my ( $temp, @results ) = '';

### Fast forward past header
while (<>) {
  last if m/<eoh>\s+$/i;
}

### While there are records remaining...
while (<>) {
  $temp .= $_;

  ### Process if end of record tag reached
  if (m/<eor>\s+$/i) {
    my %hash;
    $temp =~ s/\n//g;
    $temp =~ s/<eoh>.*//i;
    $temp =~ s/<eor>.*//i;
    my @arr = split( '<', $temp );
    foreach (@arr) {
      next if (/^$/);
      my ( $key, $val ) = split( '>', $_ );
      $key =~ s/:.*$//;
      $hash{$key} = $val unless ( $key eq '' );
    }
    push @results, \%hash;
    $temp = '';
  }
}

# example: just pull out CALL and GRIDSQUARE for each record that has them
foreach (@results) {
  next unless exists( $_->{GRIDSQUARE} );
  print join( "\t", $_->{CALL}, $_->{GRIDSQUARE} ), "\n";
}

exit;

If you want some real code to manipulate ADIF files, adifmerg works.