LINUX.ORG.RU

[Perl] Разбивка длинной строки

 


0

0

Доброго времени суток!

Имеется длинная строка (240 символов), в которой зашифрованы показания кучи датчиков. Строку эту нужно разбить на подстроки разной (заранее известной) длины, каждую подстроку преобразовать и таким образом получить эти показания. С преобразованием проблем нет, но я подозреваю, что для каждого преобразования отдельно получать свою подстроку довольно накладно. Есть ли возможность сразу разбить исходную строку на подстроки заданной длины, и уже потом каждую обрабатывать по отдельности?

Ответ на: комментарий от name_no

Спасибо, интересная мысль. Только вот два вопроса.

1. Регэксп будет довольно длинный — в строке зашифрованы показания около 40 датчиков. Не окажется ли обработка строки по регэкспу медленнее, чем явные вызовы substr?

2. (нубский вопрос) Можно пример использования регэкспов подобного рода? Я так понимаю, что результат преобразования должен присваиваться массиву. Я не перл-хакер, я только учусь :-)

decadent
() автор топика
Ответ на: комментарий от decadent

substr будет быстрее

или аналог сишной функции scan

use String::Scanf;

($temp, $speed, $size) = sscanf('%4s %3s %5s','1234 123 12345');

ligverd
()
Ответ на: комментарий от decadent

Сорок вызовов substr или один вызов регексп - я не уверен, что будет быстрее, если честно.

Использовать регексп можно, например, так:

my $str = 'long_string';
$str =~ m/^(\w{2})(\w{10})(\w{5})$/;
printf "temp: %i; date: %s; pressure: %s", $1, $2, $3;
как можно догадаться, $1, $2, $3 соответствуют скобочкам в регекспе.

Другой вариант:

my $str = 'long_string';
my @arr = $str =~ m/^(\w{2})(\w{10})(\w{5})$/;
printf "temp: %i; date: %s; pressure: %s", @arr;

name_no ★★
()
Ответ на: комментарий от name_no

Большое спасибо, теперь все понятно! Попробую оба варианта — и с sscanf, и с регэкспом.

decadent
() автор топика

Если заранее известны длины строк, регэксп не нужен. Используйте unpack.

anonymous
()
Ответ на: комментарий от wlan

Интересно, как вы будете делать split следующей строки: «test1testtest255», длина первой части 5, второй 4, третьей 6, четвертой 1.

anonymous
()
Ответ на: комментарий от anonymous
#!/usr/bin/perl

use strict;
use warnings;

my @array = "test1testtest255";

my $part1 = shift split /\w{5}/, @array;

my $part2 = shift split /\w{4}/, @array;

my $part3 = shift split /\w{6}/, @array; 

my $part4 = shift split /\w{1}/, @array;

код вбивал прям тут и не отлаживал, примерно так.

wlan ★★
()
Ответ на: комментарий от wlan
#!/usr/bin/perl

use strict;
split(/ */, 'test1testtest255');

my @part1 = @_[0..4];
my @part2 = @_[5..8];
my @part3 = @_[9..14];
my @part4 = @_[15];

print "@part1\n@part2\n@part3\n@part4\n";
hawaii-2% ./test.pl
t e s t 1
t e s t
t e s t 2 5
5

да согласен, через сплит велосипедно получается, красивее было бы через регекспы

wlan ★★
()
Ответ на: комментарий от anonymous

чо вы прикопались, я вообще вендузятнек

wlan ★★
()
Ответ на: комментарий от anonymous

> @parts = unpack(«A5 A4 A6 A1», «test1testtest255»);

Спасибо, действительно there is mote than one way to do it :-) Я уже через регэксп сделал — работает вроде бы нормально.

decadent
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.