Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

what's this loo code?

by John M. Dlugosz (Monsignor)
on Feb 04, 2003 at 17:33 UTC ( [id://232599]=perlquestion: print w/replies, xml ) Need Help??

John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

jmcnamara wrote
# wc perl -le 'print $==()=<>' file
Although I looked up $= in perlvar, I can't make heads nor tails of it! I read $= is assigned () is assigned <> with the assignments being right-associative. But that doesn't make sence, and even if it did, just printing the value of the assignment is normally no different from just printing the rhs, so what's the point?

Baffled,
—John

Replies are listed 'Best First'.
Re: what's this loo code? (*slurp*)
by tye (Sage) on Feb 04, 2003 at 17:58 UTC

    I waited and two explanations have already appeared as I hoped and expected...

    But I wanted to mention my first impression when I saw that code in jmcnamara's node: "Oh, that takes way too much memory and will fail for files that don't fit within your available swap space".

    The number of possible Perl one-liners that print a line count and don't suffer from requiring way too much memory for large files is quite huge. I'll shoot for a very straight-forward one:    perl -le '1 while <>; print $.' file I'm almost certain you can make that faster or shorter (without reintroducing the memory hog aspect of it), but I really don't care to do either.

                    - tye
      I'm almost certain you can make that faster or shorter

      I can't imagine it making a significant dent in speed for small(er) files, but -l (sh|c)ould be omitted.

      Perhaps...

      perl -ne 'END{ print $., $/ }' file

      ...or...

      perl -ne 'END{ print $. }' file

          --k.



      But I wanted to mention my first impression when I saw that code in jmcnamara's node: "Oh, that takes way too much memory and will fail for files that don't fit within your available swap space".

      I hope you realise that I was aware of that. :-)

      This snippet's only real value is as a mild curiosity. When I first posted it here I wrote: "There are many ways of doing this and most of them are better".

      If I really wanted a line count I would use one of the following in this order of preference:

      wc -l file awk 'END{print NR}' file perl -nle 'END{print $.}' file
      --
      John.

      Efficient:
      perl -ne'BEGIN{$/=\65536} $a+=tr/\n//; END{print"$a\n"}' file
      Pity there's no way to set $/ to a reference to a number using a switch.

      Makeshifts last the longest.

        If the last line doesn't end with a \n (that is, \n is not the last character in the last chunk) you'll be off by one.
      I guess the comments throw off my expectations, too. Since when does "wc" stand for "number of lines in a file"? The dictionary says it's a British toilet (a.k.a. "the loo") and it could be an acronym for word count, so I was trying to figure out how that was counting words.

        The wc utility counts words, lines, and characters in a file. wc -l tells wc to only display the number of lines.

        --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
Re: what's this loo code?
by jdporter (Paladin) on Feb 04, 2003 at 17:44 UTC
    just printing the value of the assignment is normally no different from just printing the rhs, so what's the point?
    It's all about context. Just printing the RHS evaluates it in list context. The assignment to $= (an unused global variable) forces the assignment to occur in scalar context.
    And there's the trick: evaluating a list assignment in scalar context returns the number of items that are (or would be) assigned.
    That is why this snippet works to print the number of lines of input.

    jdporter
    The 6th Rule of Perl Club is -- There is no Rule #6.

Re: what's this loo code?
by clairudjinn (Beadle) on Feb 04, 2003 at 20:43 UTC
    I wrote to Larry about this sort of thing once:

    me: The following is from page 75 in the Camel: "List assignment in scalar context returns the number of elements produced by the expression on the right side of the assignment:

    $x = ( ($a, $b) = (7,7,7) ); #set $x to 3, not 2

    why. how.

    Larry on why: Because then you can use it for a boolean value:

    while (($a,$b) = somefunc()) { ... }

    If it used the number of elements on the left, it would always be true.

    Larry on how: It counts them. :-)

Re: what's this loo code?
by BrowserUk (Patriarch) on Feb 04, 2003 at 19:04 UTC

    If you just want the line count (no slurping).

    perl -ne"}{die" file

    If you want the filenames too

    perl -ne"}{die$ARGV" *


    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      that's interesting. how does that '}{die' thing work ? why doesn't perl complain of mismatched braces or something

        Take a look at the documentation for the -p and -n switches in perlrun. In prasee er...short, it says

        -p causes Perl to assume the following loop around your program, which ma +kes it iterate over filename arguments somewhat like sed: LINE:while (<>) { # your program goes here } continue { print or die "-p destination: $!\n"; }

        If you substitute the 'program' eg. "}{die" where the comment above says " your program goes here", then you willl see how the thing works.


        Examine what is said, not who speaks.

        The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

Re: what's this loo code?
by pfaut (Priest) on Feb 04, 2003 at 17:49 UTC

    I think whatever perl normally uses $= for is irrelevant. The idea is to use the assignment to a scalar to evaluate the array in scalar context. The anonymous array exists to evaluate the <> in list context. So, slurp the file into the anonymous array, then assign the size of the array to $= and print it.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
      This is a bogus explanation I'm afraid. The anonymous array you speak of doesn't exist afaik, but I wouldn't bet my life on it. But what I'm sure of is that then assign the size of the array to $= is wrong. From perlop: "a list assignment in scalar context returns the number of elements produced by the expression on the right hand side of the assignment." What's on the LHS is irrelevant.   print scalar(($a, $b) = ('a','b','c')); # prints '3' ihb
Re: what's this loo code?
by steves (Curate) on Feb 04, 2003 at 17:55 UTC

    I don't see the point, but breaking it down:

    • Read from file: <>
    • Read in array context; i.e., get all lines from file: ()=<>
    • Assign those read lines to $=. That's the page length for formatted output: $==()
    Basically it's saying, make the format page length the size of the number of lines in file. But just printing that doesn't really do a whole lot unless I'm missing something ...

      Assign those read lines to $=

      No. Assign the length of the right hand side expression in the assignment.

      ihb
Re: what's this loo code?
by Anonymous Monk on Feb 05, 2003 at 03:51 UTC
    looks like: the whole contents of file are being read by =<> into an anonymous scalar =() and assigned to the lines per page variable $= ...so that to me means the whole file is printed as one page, ie no "press any key to continue" during viewing. I might not be perfect in my interpretation, but i don't think it's far off the mark either. chris_piechowicz@hotmail.com

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://232599]
Approved by Enlil
Front-paged by Enlil
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2024-03-28 20:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found