LINUX.ORG.RU

Возможно ли на regexp perl удалить определенное число байтов из строки?

 ,


1

1

Есть строка текста в которой в произвольном месте может содержаться «мусорный» текст который нужно вычистить. У «мусора» следующие параметры он оканчивается на \x00\x00 (в hex представлении), а в начале \xE3\x33 но при этом он не всегда находится в самом начале иногда перед ним бывает 1 или 2 символа. При этом длинна «мусорной» строки всегда 70 байт. Встречается «мусор» произвольное число раз.

Возможно ли на Perl составить такое регулярное выражение или два три выражения которое удаляло бы ненужное?

Забыл добавить подобная последовательность (\x00\x00) может быть не один раз внутри «мусора». И начинается не строго с \xE3\x33. В начале бывает еще 1-2 символа произвольных, но длинна всегда 70 байт.

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

И начинается не строго с \xE3\x33

длина всегда 70 байт

Пиши автомат. Хотя если нет строгого начального маркера, то весело, конечно.

Либо можно взять все не пересекающиеся подстроки, которые заканчиваются на терминальные байты и вырезать те, которые нужной длины.

Lilly
()
Последнее исправление: Lilly (всего исправлений: 1)
Ответ на: комментарий от Lilly

Я думал что от \xE3\x33 отложить 68-70 байт, там найти \x00\x00, а потом от них уже ровно 70 байт отрезать. Не выйдет? А что такое автомат?

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

Либо можно взять все не пересекающиеся подстроки, которые заканчиваются на терминальные байты и вырезать те, которые нужной длины.

А как это сделать? Одним выражением как я понял я не обойдусь.

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

Если у тебя нет чёткого начала мусорной строки («В начале бывает еще 1-2 символа произвольных, но длинна всегда 70 байт»), то что-то в духе «любые 70 символов а потом вот эти два байта» может сработает даже, но я не стал бы так писать, учитывая, что терминальные байты могут повторяться и ты не сможешь отличить это действительно конец мусора или ты в центре мусорной строки и должен искать ещё.

Хотя, если строку можно развернуть, тогда всё просто: находишь первые конечные байты (теперь они «начальные»), отрезаешь 70, опять находишь и так пока не обойдёшь всё. Такое можно и безопасно в регулярку завернуть, думаю, но код не дам. Это будет даже проще и быстрее, чем писать конечный автомат, который будет следить за текущим состоянием «курсора» в строке.

Короче, делай reverse и потом while. ;)

Lilly
()
Ответ на: комментарий от gedisdone

Конечный, да. Флаги в духе «А мы видели начало строки?», «Сколько мы уже видели байт с начала строки» и немного логики, но при ближайшем рассмотрении легко написать переусложнённую кашу, так что reverse + while предложенные выше будет легко понять читающему, просто написать, сплошная выгода, короче.

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

Спасибо за наводки, попробую завтра сделать, уже не на работе. И отпишусь по результатам.

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

Если мусорные строки не могут перекрываться, то так вроде должно сработать:

s/(.{0,2}\xe3\x33.{64,66}\x00{2})(?(?{ length($1) == 70 })|(*FAIL))//g
Jini ★★
()

есть утилька bbe - умеет работать с байтовыми последовательностями.

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

Спасибо за подсказку. Так и сделал, перевернул строку, а потом искал \x00\x00 и от них уже искал 70 байт и вырезал, потом строку обратно переворачивал. Примерно так: $row = reverse($row); $row=~s/\x00\x00.{68}//g; $row = reverse($row); И все получилось. Еще раз всем спасибо за помощь.

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