Работа с подстроками
Проблема
Требуется получить или модифицировать не целую строку, а лишь ее часть. Например, вы прочитали
запись с фиксированной структурой и теперь хотите извлечь из нее отдельные поля.
Решение
Функция substr предназначена для чтения и записи отдельных байтов строки:
$value = substr($string, $offset, $count);
$value = substr($string, $offset);
substr($stnng, $offset, $count) = $newstring;
substr($string, $offset) = $newtail;
Функция unpack ограничивается доступом только для чтения, но при извлечении нескольких подстрок работает быстрее:
# Получить 5-байтовую строку, пропустить 3,
# затем две 8-байтовые строки, затем все остальное
($leading, $s1, $s2, $trailing) =
unpack("A5 хЗ A8 A8 A*", $data);
# Деление на группы из пяти байт
@fivers = unpack("A5" x (length($string)/5), $string);
# Деление строки на отдельные символы
@chars = unpack("A1" x length($string), $string);
Комментарий
В отличие от многих языков, в которых строки представлены в виде массива байтов (или символов), в Perl
они относятся к базовым типам данных. Это означает, что для работы с отдельными символами или подстроками
применяется функция unpack или
substr.
Второй аргумент функции substr (смещение) определяет начало интересующей вас подстроки;
положительные значения отсчитываются от начала строки, а отрицательные — с конца. Если смещение равно 0,
подстрока начинается с начала. Третий аргумент определяет длину подстроки.
$stnng = "This is what you have";
# +012345678901234567890 Прямое индексирование (слева направо)
# 109876543210987654321- Обратное индексирование (слева направо)
0 соответствует 10, 20 и т. д.
$first = substr($strinng, 0, 1); # "Т"
$start = substr($string, 5, 2); # "is"
$rest = substr($string, 13); # "you have"
$last = substr($string, -1); # "e"
$end = substr($string, -4); # "have"
$piece = substr($strinng, -8, 3); # "you"
Однако функция substr позволяет не только просматривать части строки, но и изменять их. Дело в том, что
substг относится к экзотической категории левосторонних функций, то есть таких, которым при вызове можно
присвоить значение. К тому же семейству относятся функции
vec,
pos и
keys (начиная с версии 5.004).
При некоторой фантазии функции local и ту также можно рассматривать как левосторонние.
$string = "This is what you have";
print $string;
This is what you have
substr($string, 5, 2) = "wasn't"; # заменить "is" на "wasn't"
This wasn't what you have
substr($string, -12) = "ondrous"; # "This wasn't wondrous"
This wasn't wondrous
substr($string, 0, 1) = ""; # Удалить первый символ
his wasn't wondrous
substr($string,-10) = "" # Удалить последние 10 символов
his wasn't
Применяя оператор =" в сочетании с операторами
s///,
m// или
tr///, можно заставить их работать только с
определенной частью строки:
# =" применяется для поиска по шаблону
if (substr($string, -10) =' /pattern/) {
print "Pattern matches in last 10 characters\n";
}
# подставить "at" вместо "is", ограничиваясь первыми пятью символами
substr($string, 0, 5) =" s/is/at/g;
Более того, подстроки даже можно поменять местами, используя с каждой стороны присваивания несколько вызовов substr:
# Поменять местами первый и последний символ строки
$а = "make a hat";
(substr($a,0,1), substr($a,-1)) = (substr($a,-1), substr($a,0,1));
print $a;
take a ham
Хотя функция unpack не является левосторонней, она работает значительно быстрее substr,
особенно при одновременном извлечении нескольких величин. В отличие от substr она не поддерживает
непосредственные смещения. Вместо этого символ "х" нижнего регистра с числом пропускает заданное
количество байт в прямом направлении, а символ "X" верхнего регистра — в обратном направлении.
# Извлечение подстроки функцией unpack
$а = "То be or not to be";
$b = unpack("x6 A6", $a); # Пропустить 6 символов, прочитать 6 символов
print $b;
or not
($b, $c) = unpack("x6 A2 X5 A2", $a); # Вперед 6, прочитать 2;
# назад 5, прочитать 2
print "$b\n$c\n";
or
be
Иногда строка «режется» на части в определенных позициях. Предположим, вам захотелось установить
позиции разреза перед символами 8, 14, 20, 26 и 30 — в каждом из перечисленных столбцов начинается новое поле.
В принципе можно вычислить форматную строку unpack - "А7 А6 А6 А4 А*", но программист на Perl по
природе лепив и не желает попусту напрягаться. Пусть за него работает Perl. Воспользуйтесь приведенной ниже функцией cut2fmt
sub cut2fmt {
my(@positions) = @_;
my $template = ' ' ;
my $lastpos = 1;
foreach $place(@positions) {
$template .= "A" , ($place - $lastpos). " ";
$lastpos = $place;
}
$template .= "А*";
return $template;
}
$fmt = cut2fmt(8, 14, 20, 26, 30);
print "$fmt\n";
A7 A6 A6 A6 A4 A*
Возможности функции unpack выходят далеко за пределы обычной обработки текста. Она также о
беспечивает преобразование между текстовыми и двоичными данными.
См. такжеОписание функций
unpack и substr
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|