#!/usr/bin/env perl use strict; use warnings; use Text::CSV; my $psv = Text::CSV::->new({sep_char => '|', allow_whitespace => 1}) or die 'Text::CSV problem: ', Text::CSV::->error_diag(); my %data_for; while (my $row = $psv->getline(\*DATA)) { my ($user, $role, $type, $date) = @$row; push @{$data_for{$user}{$type}}, $role; push @{$data_for{$user}{dates}{$type}}, $date; } $psv->eol("\n"); for (sort keys %data_for) { $psv->print(\*STDOUT, [ $_, join(',', @{$data_for{$_}{added} || []}), join(',', @{$data_for{$_}{deleted} || []}), join(',', @{$data_for{$_}{dates}{added} || []}, @{$data_for{$_}{dates}{deleted} || []} ), ]); } __DATA__ abc|admin |added | 01072015 abc|developer |deleted |02072015 abc|deploy |added |03072015 xyz |admin |deleted |04072015 xyz| deploy|deleted|05072015 cdf|deploy|added|06072015