开发者

perl equivalent of python array.array(typecode, ..)

I am trying to translate a python script to perl but currently stuck at couple of code snipets.

For instance how to write following python code in perl? (without using any perl array related packages)

# packet here is a binary string
data = array.array( 'h', ( ord( packet[i] ) for i in range( start, end ) ) )
FILE.write(data);

My (failed) attempt:

my @data;
foreach $i ( $start .. $end ) {
   $data[$i] = ord( substr( $packet, $i, 1) );  # Assuming that perl's ord = python's ord
}

print FILE @data;

@ysth, the actual input is a large binary file and in excitment of posting my first question here I forgot to generate a sample input and ouput, sorry about that. For completeness find below the sample input and output.

input: ['a', 'b', 'c', 'd'] #think this as packet contents, start=0, end=4

ouput in python:

> cat py.out | xxd
0000000: 6100 6200 6300 6400                      a.b.c.d.

output in perl:

> cat pl.out | xxd
0000000: 3937 3938 3939 3130 30                   979899100

@Pedro Silva, As I understand in first line of your suggestion you just replace for loop with map functionality, the effect is same. The unpack 'W*' r开发者_StackOverfloweturns error as W is not a valid type (perl 5.8.8).


edit

You need to clarify what you're saying. On my python (2.7.2), this is wrong:

FILE.write(data)

because data needs to be a string. I think what you mean to say instead is:

data.tofile(FILE)

Anyway, is this what you want?

print pack("s*", unpack("C*", "abcd"))
# piped through xxd => 0000000: 6100 6200 6300 6400     a.b.c.d.

Have a look through perldoc -f pack for the correct template string to use. Since you don't have access to W (unsigned wchar), i'm using C (unsigned char). s is a signed short (corresponding to python's h.)

/edit

There are no typed arrays in Perl. ord returns the numeric value of the first character of its argument.

Assuming this is what you want, just map the list resulting from splitting $packet on each character to @data, transforming each element with ord (the argument $_ is implicitly given.)

my @data = map { ord } split //, $packet; # or
my @data = unpack 'W*', $packet;          

Optionally, using a range different from the actual lower and upper bounds on $packet:

(split //, $packet)[$start .. $end];    # or
 split //, substr $packet, $start, $end # ysth's version
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜