http://qs321.pair.com?node_id=603363


in reply to Read file line by line and check equal lines

I thought I would tempt you with this version.
#!/usr/bin/perl use strict; use warnings; my $previous; &unique while(<DATA>); sub unique { return if $previous and $previous eq $_; print; $previous = $_; } __DATA__ a1a a1a b1b c1c c1c d1d d1d e1e f1f g1g g1g h1h h1h i1i j1j k1k k1k k1k

-=( Graq )=-

Replies are listed 'Best First'.
Re^2: Read file line by line and check equal lines
by Anno (Deacon) on Mar 06, 2007 at 13:07 UTC
    Why the sub call with a leading ampersand (&unique)? Since perl 5 that form is no longer necessary and has the side-effect of using (and exposing)the caller's @_ instead of building its own. You are not using @_ at all, so it's unnecessary.

    Instead, your sub uses two global variavles, one lexical ($previous) and the package variable $_. That should be avoided except in very special cases. In this case it is hard to see why you use a sub at all. Just expand the code in the loop body. That would be clearer.

    Anno

Re^2: Read file line by line and check equal lines
by duff (Parson) on Mar 06, 2007 at 17:27 UTC

    That doesn't exactly solve the stated problem, does it? As I read it, the OP only wants those lines that only appear one time in the input. What you've given is a way to display a given line from the input at most one time.

    Here's a solution (untested, so there's probably boundary problems) that only needs to keep at most 3 lines in memory under the constraint that the lines are already sorted.

    #!/usr/bin/perl use strict; use warnings; my ($p1, $p2); while(<DATA>) { next unless $p1 and $p2; if ($p2 eq $p1) {$p2 = $p1 = undef; redo; } if ($p2 ne $p1) { print $p2; next; } } continue { $p2 = $p1; $p1 = $_; } __DATA__ a1a a1a b1b c1c c1c d1d d1d e1e f1f g1g g1g h1h h1h i1i j1j k1k k1k k1k