文字単位のdiffを取って、いい感じにHTMLで表示したくなることありませんか? ぼくはあります。
ただ、この前それをやりたくなったのが10年以上前で、すっかり忘れてまた作り直すはめになったので、自分用を兼ねてメモしておきます。
欲しいのはこういうやつです。
$ echo -e "今日はいい天気ですね。\t今日はとてもいい天気でしたね" | xxx
今日は<u>とても</u>いい天気で<s>す</s><u>した</u>ね<s>。</s>
入力はタブ区切りで、左右の行は常に対応しているとします。対応していない場合はちゃんとしたツールを使って何とかしたほうがいいと思いますが、ここでは行は対応しているとして、その場合の文字単位のdiffをワンライナーで取ることにします。
Perlで書いたワンライナーが次のものです。
perl -MFile::Temp -Mutf8 -CSD -F/\\t/ -nale 'for $i(0..1) { ($fh[$i], $fname[$i]) = File::Temp::tempfile(UNLINK=>1); binmode $fh[$i], ":utf8"; @{$l[$i]} = split//, $F[$i]; print {$fh[$i]} $_ for @{$l[$i]}; close $fh[$i]; } for (reverse grep { m{^\d}; } map { chomp; $_; } `diff $fname[0] $fname[1]`) { @t = map { m{^(\d+),(\d+)$} ? [$1-1, $2-1] : m{^(\d+)$} ? [$1-1, $1-1] : $_; } split/([acd])/; @new = @{$l[1]}[$t[2]->[0]..$t[2]->[1]]; if ($t[1] eq "a") { splice @{$l[0]}, $t[0]->[0]+1, 0, "<u>", @new, "</u>"; } elsif ($t[1] eq "d") { splice @{$l[0]}, $t[0]->[1]+1, 0, "</s>"; splice @{$l[0]}, $t[0]->[0], 0, "<s>"; } else { splice @{$l[0]}, $t[0]->[1]+1, 0, "</s><u>", @new, "</u>"; splice @{$l[0]}, $t[0]->[0], 0, "<s>"; } } print join("", @{$l[0]});'
これを使うと、上のことが実現できます。
echo -e "今日はいい天気ですね。\t今日はとてもいい天気でしたね" | perl -MFile::Temp -Mutf8 -CSD -F/\\t/ -nale 'for $i(0..1) { ($fh[$i], $fname[$i]) = File::Temp::tempfile(UNLINK=>1); binmode $fh[$i], ":utf8"; @{$l[$i]} = split//, $F[$i]; print {$fh[$i]} $_ for @{$l[$i]}; close $fh[$i]; } for (reverse grep { m{^\d}; } map { chomp; $_; } `diff $fname[0] $fname[1]`) { @t = map { m{^(\d+),(\d+)$} ? [$1-1, $2-1] : m{^(\d+)$} ? [$1-1, $1-1] : $_; } split/([acd])/; @new = @{$l[1]}[$t[2]->[0]..$t[2]->[1]]; if ($t[1] eq "a") { splice @{$l[0]}, $t[0]->[0]+1, 0, "<u>", @new, "</u>"; } elsif ($t[1] eq "d") { splice @{$l[0]}, $t[0]->[1]+1, 0, "</s>"; splice @{$l[0]}, $t[0]->[0], 0, "<s>"; } else { splice @{$l[0]}, $t[0]->[1]+1, 0, "</s><u>", @new, "</u>"; splice @{$l[0]}, $t[0]->[0], 0, "<s>"; } } print join("", @{$l[0]});'
今日は<u>とても</u>いい天気で<s>す</s><u>した</u>ね<s>。</s>
中でdiffコマンドを実行しているので、diffコマンドが入っていることが必要です。