Perl-эквивалент Python array.array (typecode, ..) - PullRequest
4 голосов
/ 04 июля 2011

Я пытаюсь перевести скрипт Python в Perl, но в настоящее время застрял на нескольких фрагментах кода.

Например, как написать следующий код Python в Perl?(без использования пакетов, относящихся к массиву Perl)

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

Моя (неудачная) попытка:

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 , фактический ввод -большой двоичный файл и в радости от размещения моего первого вопроса здесь я забыл сгенерировать пример ввода и вывода, извините за это.Для полноты найдите ниже пример ввода и вывода.

input: ['a', 'b', 'c', 'd'] # подумайте как содержимое пакета, start = 0, end = 4

вывод в python:

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

вывод в perl:

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

@ Pedro Silva , как я понимаю в первой строкеиз вашего предложения вы просто замените цикл с функциональностью карты, эффект тот же.Распакованный W * возвращает ошибку, так как W недопустимый тип (perl 5.8.8).

1 Ответ

5 голосов
/ 04 июля 2011

редактировать

Вы должны уточнить, что вы говорите. На моем питоне (2.7.2) это неправильно:

FILE.write(data)

потому что data должна быть строкой. Я думаю, что вы хотите сказать вместо этого:

data.tofile(FILE)

В любом случае, это то, что вы хотите?

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

Просмотрите perldoc -f pack правильную строку шаблона для использования. Поскольку у вас нет доступа к W (неподписанный wchar), я использую C (неподписанный символ). s является подписанным коротким (соответствует h. Python)

/ редактировать

В Perl нет типизированных массивов. ord возвращает числовое значение первого символа его аргумента.

Предполагая, что это именно то, что вам нужно, просто сопоставьте список, полученный в результате разбиения $packet для каждого символа, на @data, преобразовав каждый элемент с ord (аргумент $_ неявно задан).

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

При желании можно использовать диапазон, отличный от фактических нижних и верхних границ $packet:

(split //, $packet)[$start .. $end];    # or
 split //, substr $packet, $start, $end # ysth's version
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...