#!/usr/bin/perl
use 5.001 ; use strict ; use warnings ;
use Getopt::Std ; getopts ':~+12f' , \my %o ;
use autodie qw[ open ] ;
my %first ; # 最初に見た
my %last ;
unshift @ARGV , splice @ARGV , 1 , 1 if $o{'~'} ; # 条件次第で先頭とその次を入れ替える。
open my $FH , '<' , shift @ARGV ;
$SIG{ INT } = sub { close $FH ; exit 130 } ;
while ( <$FH> ) {
chomp ;
$first { $_ } //= $. ;
$last { $_ } = $. unless $o{f} ;
}
close $FH ;
#$. = 0 ;
while ( <> ) {
chomp ;
if ( exists $first { $_ } ) {
delete $first { $_ }
}
elsif ( $o{'+'} ) {
$first { $_ } = "+$." ;
}
}
unless ( $o{':'} )
{
for ( sort keys %first ) {
print "$_\n" ;
}
}
else
{
for ( sort { $first{$a} <=> $first{$b} } keys %first ) {
my $prefix = do { ! exists $last{$_} || $o{1} && $first{$_} eq $last{$_} ? "$first{$_}" : "$first{$_}-$last{$_}" } ;
print "$prefix:\t$_\n" ;
}
}
=encoding utf8
=head1
$0 file1 file2
$0 file1 < file2
cat file2 | $0 file1
file1 のどこかの行にあって、file2 にないものを抽出する。
メモリの消費は、file1の各行の異なる行の数に応じたものになる。
オプション :
-~ : file1 と file2 の順序を交換する。
-: : 出力の際に、各要素が最後に何行目に現れたかを出力する。
-1 ; 出力の各要素の、出現行番号の最初と最後が一致する場合は、ひとつにまとめる。
-f ; 最初意外は見ないことで、メモリの消費を抑制する。
-+ ; file2 にあって、file1 にはなかった行要素も抽出する。この場合は、-: の行番号出力指定時に、+記号を付加する。
開発上のメモ :
-2 で、標準エラー出力に、逆の差分の結果を出したい。
=cut
## ヘルプの扱い
sub VERSION_MESSAGE {}
sub HELP_MESSAGE {
use FindBin qw[ $Script ] ;
$ARGV[1] //= '' ;
open my $FH , '<' , $0 ;
while(<$FH>){
s/\$0/$Script/g ;
print $_ if s/^=head1// .. s/^=cut// and $ARGV[1] =~ /^o(p(t(i(o(ns?)?)?)?)?)?$/i ? m/^\s+\-/ : 1;
}
close $FH ;
exit 0 ;
}