Perl Advent Calendar 2006-12-18

What's the diff between a biscuit and a reindeer?

by Jerrad Pierce

You can't dunk a reindeer in your tea! <voice style="alf">Ha! I kill me</voice>

Speaking of diffs… Thanks to Dominus' powerful and arcane Algorithm::Diff, now maintained by Tye McQueen, we have the versatile Text::Diff, capabable of generating a variety of output formats including old style diff:

0a1
> Rudolph
5,6c6,7
< Dunder
< Blixem
---
> Donder
> Blitzen
Context diff:
***************
*** 1,8 ****
  Dasher
  Dancer
  Prancer
  Vixen
! Dunder
! Blixem
  Cupid
  Comet
--- 1,9 ----
+ Rudolph
  Dasher
  Dancer
  Prancer
  Vixen
! Donder
! Blitzen
  Cupid
  Comet
Unified diff:
@@ -1,8 +1,9 @@
+Rudolph
 Dasher
 Dancer
 Prancer
 Vixen
-Dunder
-Blixem
+Donder
+Blitzen
 Cupid
 Comet
And last but not least, a tabular format reminiscent of sdiff:
+--+---------+--+---------+
|  |         * 0|Rudolph  *
| 0|Dasher   | 1|Dasher   |
| 1|Dancer   | 2|Dancer   |
| 2|Prancer  | 3|Prancer  |
| 3|Vixen    | 4|Vixen    |
* 4|Dunder   * 5|Donder   *
* 5|Blixem   * 6|Blitzen  *
| 6|Cupid    | 7|Cupid    |
| 7|Comet    | 8|Comet    |
+--+---------+--+---------+

While Text::Diff lacks a proper sdiff output mode 1, if you prefer this sparser style you can could easily create one since the module implements formatting styles as subclasses.

Also note that the name is a bit of a minsomer. As the POD points out, and our sample code demonstrates, this module is intended to, "perform diffs on files and record sets." The diff function will accept data from scalar refs, filehandles, filenames, array refs, and callbacks. Its acceptance of arrays and strings means that Text::Diff can even be used as a replacement for the dated Data::Diff in debugging (the latter was uploaded to CPAN in 2004, but the POD dates it to 1998) though you may need to pass through Data::Dumper first.

mod18.pl


   1 use Text::Diff;
   2 
   3 #See http://www.snopes.com/holidays/christmas/donner.asp
   4 my @classic = map{"$_\n"}  #As a line-oriented algorithm you need \n for beauty
   5   qw/Dasher Dancer Prancer Vixen Dunder Blixem Cupid Comet/;
   6 my @modern  = map{"$_\n"}
   7   qw/Rudolph Dasher Dancer Prancer Vixen Donder Blitzen Cupid Comet/;
   8 
   9 print diff(\@classic, \@modern, {STYLE=>'OldStyle'}), "\n\n";
  10 print diff(\@classic, \@modern, {STYLE=>'Context'}),  "\n\n";
  11 print diff(\@classic, \@modern, {STYLE=>'Unified'}),  "\n\n";
  12 print diff(\@classic, \@modern, {STYLE=>'Table'});
1. sdiff -l output for those unfamiliar with it
              > Rudolph
Dasher        (
Dancer        (
Prancer       (
Vixen         (
Dunder        | Donder
Blixem        | Blitzen
Cupid         (
Comet         (