/usr/share/doc/libtext-csv-xs-perl/examples/csvdiff is in libtext-csv-xs-perl 0.85-1build1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | #!/usr/bin/perl
use strict;
use warnings;
sub usage
{
my $err = shift and select STDERR;
print "usage: csvdiff [--no-color] [--html] file.csv file.csv\n",
" provides colorized diff on sorted CSV files\n",
" assuming first line is header and first field is the key\n";
exit $err;
} # usage
use Getopt::Long qw(:config bundling nopermute );
my $opt_c = 1;
my $opt_h = 0;
my $opt_o = "";
GetOptions (
"help|?" => sub { usage (0); },
"c|color|colour!" => \$opt_c,
"h|html" => \$opt_h,
"o|output=s" => \$opt_o,
) or usage (1);
@ARGV == 2 or usage (1);
if ($opt_o) {
open STDOUT, ">", $opt_o or die "$opt_o: $!\n";
}
use HTML::Entities;
use Term::ANSIColor qw(:constants);
use Text::CSV_XS;
my $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 0 });
if ($opt_h) {
binmode STDOUT, ":utf8";
print <<EOH;
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>CFI School updates</title>
<meta name="Generator" content="perl $]" />
<meta name="Author" content="@{[scalar getpwuid $<]}" />
<meta name="Description" content="CSV diff @ARGV" />
<style type="text/css">
.rd { background: #ffe0e0; }
.gr { background: #e0ffe0; }
.b0 { background: #e0e0e0; }
.b1 { background: #f0f0f0; }
.r { color: red; }
.g { color: green; }
</style>
</head>
<body>
<h1>CSV diff @ARGV</h1>
<table>
EOH
$::{RED} = sub { "\cA\rr"; };
$::{GREEN} = sub { "\cA\rg"; };
$::{RESET} = sub { ""; };
}
elsif (!$opt_c) {
$::{$_} = sub { "" } for qw( RED GREEN RESET );
}
my @f;
foreach my $x (0, 1) {
open my $fh, "<", $ARGV[$x] or die "$ARGV[$x]: $!\n";
while (1) { $_ = $csv->getline ($fh) or last; @$_ and push @{$f[$x]}, $_ }
}
my @n = map { $#{$f[$_]} } 0, 1;
my @i = (1, 1);
my $hdr = "# csvdiff < $ARGV[0] > $ARGV[1]\n";
$f[$_][1+$n[$_]][0] = "\xff\xff\xff\xff" for 0, 1;
my %cls;
%cls = (
"b" => 0,
"-" => sub { "rd" },
"+" => sub { "gr" },
"<" => sub { $cls{b} ^= 1; "b$cls{b}" },
">" => sub { "b$cls{b}" },
);
sub show
{
my ($pfx, $x) = @_;
my $row = $f[$x][$i[$x]++];
if ($opt_h) {
my $bg = $cls{$pfx}->();
print qq{ <tr class="$bg">},
(map{"<td".(s/^\cA\r([gr])//?qq{ class="$1"}:"").">$_</td>"}@$row),
"</tr>\n";
return;
}
print $hdr, $pfx, " ", $pfx eq "-" ? RED : $pfx eq "+" ? GREEN : "";
$csv->print (*STDOUT, $row);
print RESET, "\n";
$hdr = "";
} # show
while ($i[0] <= $n[0] || $i[1] <= $n[1]) {
$f[0][$i[0]][0] lt $f[1][$i[1]][0] and show ("-", 0), next;
$f[0][$i[0]][0] gt $f[1][$i[1]][0] and show ("+", 1), next;
"@{[@{$f[0][$i[0]]}]}" eq "@{[@{$f[1][$i[1]]}]}" and
$i[0]++, $i[1]++, next;
foreach my $c (1 .. $#{$f[0][0]}) {
$f[0][$i[0]][$c] eq $f[1][$i[1]][$c] and next;
$f[0][$i[0]][$c] = RED . $f[0][$i[0]][$c] . RESET;
$f[1][$i[1]][$c] = GREEN . $f[1][$i[1]][$c] . RESET;
}
show ("<", 0);
show (">", 1);
}
$opt_h and print " </table>\n</body>\n</html>\n";
close STDOUT;
|