Есть строка текста в которой в произвольном месте может содержаться "мусорный" текст который нужно вычистить. У "мусора" следующие параметры он оканчивается на \x00\x00 (в hex представлении), а в начале \xE3\x33 но при этом он не всегда находится в самом начале иногда перед ним бывает 1 или 2 символа. При этом длинна "мусорной" строки всегда 70 байт. Встречается "мусор" произвольное число раз.Возможно ли на Perl составить такое регулярное выражение или два три выражения которое удаляло бы ненужное?
Забыл добавить подобная последовательность (\x00\x00) может быть не один раз внутри "мусора". И начинается не строго с \xE3\x33. В начале бывает еще 1-2 символа произвольных, но длинна всегда 70 байт.
> Забыл добавить подобная последовательность (\x00\x00) может быть не один раз внутри "мусора".
> И начинается не строго с \xE3\x33. В начале бывает еще 1-2
> символа произвольных, но длинна всегда 70 байт.На перле это делается как два пальца об асфальт, остается только понять что такое "бывает 1-2 символа" и как эти два символа отличить от остальной части строки.
Регексы требуют четкости, а не размытых формулировок.
>> Забыл добавить подобная последовательность (\x00\x00) может быть не один раз внутри "мусора".
>> И начинается не строго с \xE3\x33. В начале бывает еще 1-2
>> символа произвольных, но длинна всегда 70 байт.
> На перле это делается как два пальца об асфальт, остается только понять
> что такое "бывает 1-2 символа" и как эти два символа отличить
> от остальной части строки.
> Регексы требуют четкости, а не размытых формулировок.Согласен что нужно четко описывать, но проблема в том что эти 1-2 символа никак не отличить от нормальной строки поэтому я пошел другим путем. Сначала перевернул строку, а потом искал \x00\x00 и от них уже искал 70 байт и вырезал, потом строку обратно переворачивал.
$row = reverse($row);
$row=~s/\x00\x00.{68}//g;
$row = reverse($row);
Возможно перевороты туда сюда и не оптимальны но это работает.
> Согласен что нужно четко описывать, но проблема в том что эти 1-2
> символа никак не отличить от нормальной строки поэтому я пошел другим
> путем. Сначала перевернул строку, а потом искал \x00\x00 и от них
> уже искал 70 байт и вырезал, потом строку обратно переворачивал.
> $row = reverse($row);
> $row=~s/\x00\x00.{68}//g;
> $row = reverse($row);
> Возможно перевороты туда сюда и не оптимальны но это работает.Это сферическое "черезжопу" в вакууме.
Внизу есть решение нарезки по 70.
> Есть строка текста в которой в произвольном месте может содержаться "мусорный" текст
> который нужно вычистить. У "мусора" следующие параметры он оканчивается на \x00\x00
> (в hex представлении), а в начале \xE3\x33 но при этом он
> не всегда находится в самом начале иногда перед ним бывает 1
> или 2 символа. При этом длинна "мусорной" строки всегда 70 байт.
> Встречается "мусор" произвольное число раз.
> Возможно ли на Perl составить такое регулярное выражение или два три выражения
> которое удаляло бы ненужное?Что-то такое, если я вас верно понял.
$clean = do{ use bytes ; $str =~ s/.{68}\x00{2}(?!=\x00)//g ; $str }
>> Е> Что-то такое, если я вас верно понял.
> $clean = do{ use bytes ; $str =~ s/.{68}\x00{2}(?!=\x00)//g ; $str }Так оно не проверит на \xE3\x33. Нужно тщательнее:
$clean = do{ use bytes;
$str =~ s/\xE3\x33.{66}\x00{2}//og;
$str =~ s/.\xE3\x33.{65}\x00{2}//og;
$str =~ s/..\xE3\x33.{64}\x00{2}//og;
$str }
Три простых регекса отработают в разы быстрее одного сложного.
> Так оно не проверит на \xE3\x33. Нужно тщательнее:Если в данных не бывает \0\0, удаляемый кусок всегда 70 байт и оканчивается двумя и более \0, моего решения достаточно.
Без конкретики в условиях лучше не переусложнять.> Три простых регекса отработают в разы быстрее одного сложного.
Это не сложное выражение.
> Это не сложное выражение.(?!=\x00) - что это значит?
Есть:
(?=ххх) заглядывание вперед
(?!xxx) заглядывание вперед с отрицанием
а что у вас нифига не понятно, думаю что скорее второе.Вообще в силу формулировки афтара, его следовало бы послать ... формулировать, а не гадать не пойми на чем.
>> Это не сложное выражение.
> (?!=\x00) - что это значит?
> Есть:
> (?=ххх) заглядывание вперед
> (?!xxx) заглядывание вперед с отрицанием
> а что у вас нифига не понятно, думаю что скорее второе.
> Вообще в силу формулировки афтара, его следовало бы послать ... формулировать, а
> не гадать не пойми на чем.Думал сначала написать ?=[^\x00], а потом исправил и знак равно забыл убрать. Регулярку конечно не тестил.
Посылать неправильно. Вопрос корректный. Возможно? Возможно. Он же не попросил сразу годного в продакшен решения.
> Думал сначала написать ?=[^\x00], а потом исправил и знак равно забыл убрать.
> Регулярку конечно не тестил.
> Посылать неправильно. Вопрос корректный. Возможно? Возможно. Он же не попросил сразу годного
> в продакшен решения.Дак афтур и толком задачу не сформулировал - в оригинальной формулировке ее вообще решить невозможно.
Примерно же понятно. Есть какой-то бинарный протокол, по которому чанки данных идут с каким-то заголовком. Так-то конечно надо изучать протокол и делать unpack по формату.
Но регулярки fine too, это же перл.
> $clean = do{ use bytes ; $str =~ s/.{68}\x00{2}(?!=\x00)//g ; $str }(?!=\x00) как я понимаю эта конструкция будет искать \x00{2} после которых нет \x00, а в строке может быть и несколько кусков такого мусора. Так что не сработает. Я поступил в "лоб" развернул строку и искал уже с конца \x00{2} и потом резал 70 байт.
> (?!=\x00) как я понимаю эта конструкция будет искать \x00{2} после которых нет
> \x00, а в строке может быть и несколько кусков такого мусора.видимо тут (?!\x00), и видимо оно будет учитывать что в мусоре \x00 не только в конце две штуки, ибо исходя из твоей формулировки мусор кончается двумя \x00, про наличие внутри ни сказано ниху ... ничего.
> Так что не сработает. Я поступил в "лоб" развернул строку и
> искал уже с конца \x00{2} и потом резал 70 байт.Это какой-то бред.
Может сначала попытаться немного изучить perl regex? А не брать хау-ту рецепты без понимания?
>> $clean = do{ use bytes ; $str =~ s/.{68}\x00{2}(?!=\x00)//g ; $str }
> (?!=\x00) как я понимаю эта конструкция будет искать \x00{2} после которых нет
> \x00, а в строке может быть и несколько кусков такого мусора.
> Так что не сработает. Я поступил в "лоб" развернул строку и
> искал уже с конца \x00{2} и потом резал 70 байт.Да, ?!= - опечатка, должно быть ?!
Конструкция смотрит 2 нулевых байта, после которых нет нулевых байтов, после чего удаляет их вместе с 68 байтами стоящими перед ними.
Если \0\0 в длину удаляемой строки не входят, нужно вместо {68} написать {70}.
> Конструкция смотрит 2 нулевых байта, после которых нет нулевых байтов, после чего
> удаляет их вместе с 68 байтами стоящими перед ними.
> Если \0\0 в длину удаляемой строки не входят, нужно вместо {68} написать
> {70}.Значит я правильно понял.
> Есть строка текста в которой в произвольном месте может содержаться "мусорный" текст
> он оканчивается на \x00\x00
> (в hex представлении), а в начале \xE3\x33 но при этом он
> не всегда находится в самом начале иногда перед ним бывает 1
> или 2 символа. При этом длинна "мусорной" строки всегда 70 байт.Этому определению строки строго соответствует регексп
(?=.{0,2}\xE3\x33).{68}\x00{2}Дальше понятно, или нужно разжевывать?
>> (в hex представлении), а в начале \xE3\x33 но при этом он
>> не всегда находится в самом начале иногда перед ним бывает 1
>> или 2 символа. При этом длинна "мусорной" строки всегда 70 байт.
> Этому определению строки строго соответствует регексп(?=.{0,2}\xE3\x33).{68}\x00{2}
> Дальше понятно, или нужно разжевывать?Ага. Разжуй две ситуации, в которых твой regex не сработал:
1. Перед \xE3\x33 есть ОДИН символ
2. Перед \xE3\x33 есть ДВА символа. Строка осталась 70 байтов. А ты ожидаешь 72.
> Ага. Разжуй две ситуации, в которых твой regex не сработал:
> 1. Перед \xE3\x33 есть ОДИН символИ?
{0, 2}, если что, включает в себя 1.> 2. Перед \xE3\x33 есть ДВА символа. Строка осталась 70
> байтов. А ты ожидаешь 72.Регексп работает и ожидает 70 символов. (?=.....) — это просмотр вперёд, если что. Далее отсчет идет с начала строки.