in reply to Convert Opera Contacts in .adr format to csv

if ( $content =~ /\t/ ) { $content =~ s/\t//g; }

Why are you testing for /\t/ first?    If the substitution operator doesn't find a "\t" it will not remove anything so the first test is superfluous.    And would probably would be better to use the tr/// operator anyway:

$content =~ tr/\t//d;


if ( $line =~ /CONTACT/ ) { $line =~ s/CONTACT//;

Why are you testing for /CONTACT/ first?    Just use the substitution operator in the test:

if ( $line =~ s/CONTACT// ) {


if ( $line =~ /(.+?)=.+/ ) { unless ( $cols{$1} and $cols{$1} == 1 ) { $cols{ ucfirst lc $1 } = 1; push @cols, ucfirst lc $1; }

You are testing for an unmodified $1 but you are storing a modified $1 in the hash so how is the test supposed to work correctly?    And why the two tests on $cols{$1} when the value can only ever be either 1 or undef?



if ( $$row{$_} ) { push @rows, $$row{$_}; }

$$row{$_} is usually written as $row->{$_}.