Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re: Pack/unpack - understanding the '@' and '.' templactes

by 7stud (Deacon)
on Mar 31, 2013 at 10:01 UTC ( [id://1026345]=note: print w/replies, xml ) Need Help??


in reply to [SOLVED] Pack/unpack - understanding the '@' and '.' templactes

Also note you can set the input string's pointer at any position at any time with @:

@29 A3 @0 A3 @39 A3

Here's a full example:

use strict; use warnings; use 5.016; my $text =<<END_OF_TEXT; 1 2 3 012345678901234567890123456789012 date last first id 2/1/10 Smith 001 3/1/11 Smith Betty 002 4/2/12 Jones 003 END_OF_TEXT open my $INFILE, '<', \$text or die "Couldn't open string for reading: $!"; my $discard = <$INFILE> for (1 .. 3); while (my $line = <$INFILE>) { chomp $line; printf "%-10s %-10s %-3s %-5s \n", unpack('@20 A10 @10 A10 @30 A3 @0 A5', $line); } close $INFILE; --output:-- Smith 001 2/1/1 Betty Smith 002 3/1/1 Jones 003 4/2/1

I understand what C/xa is doing,...

Maybe not. The 'C' reads the first byte from the input string and treats it as an integer. After that read, the position pointer for the string advances to the start of the second byte. Next, '/x' says to use the integer on top of the stack as the repeat count for 'x'. What the heck is the stack and where does it come from? According to the docs, the stack is...

…an internal stack of integer arguments unpacked so far.. 

That means if you use the template 'C2 /A' on the string '\001\002hello', then the stack looks like this:

2
1

The first integer that was unpacked, 1, was placed on top of the stack, then the second integer that was read, 2, was placed on top of the stack. Subsequently, the '/A' pops the value off the top of the stack, i.e. 2, and instead of being inserted into the results array the 2 becomes the repeat count for the 'A':

my $str = "\001\002hello"; my @results = unpack 'C2 /A', $str; say "@results"; --output:-- 1 he

So what happens when you apply the template 'C/xa' to the string '\003\003\003abcd'? The 'C' says to read one byte from the input string and treat it as an integer. After that read, the position pointer for the input string advances to the start of the second byte, and the 3 from the first byte is placed on top of 'the stack':

\003\003\003abcd
    ^
    |
   position pointer after reading 'C'


stack:  3

Then '/x' pops the 3 off the stack and uses it as the repeat count for the 'x', and as a result the 3 doesn't get inserted into the results array. Then because 'x' means to skip a byte and the repeat count is 3, unpack() skips 3 bytes in the input string starting at the location of the position pointer:

\003\003\003abcd
     ^
     |
   position pointer after reading a 'C'


\003\003\003abcd
             ^
             |
   position pointer after reading 'C/x'


Finally, the 'a' in the template reads the character 'b'.

perldoc pack and perlpacktut have the briefest mention of "@" and (to my eyes) no mention of ".".

Whoever wrote the pack tutorial and pack docs should be shot. I vote for deleting the current pack tutorial and pack docs, and starting with what Loops wrote.

Replies are listed 'Best First'.
Re^2: Pack/unpack - understanding the '@' and '.' templactes
by Anonymous Monk on Mar 31, 2013 at 22:53 UTC

    Shot? I didn't know you were a sad clown 7stud

    pack/unpack had even less documentation before those pages were written up

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1026345]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2024-03-28 13:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found