Что нового

StringRegExp как найти в промежутке

maxd2007

Новичок
Сообщения
89
Репутация
0
Есть фаил который я открываю бинарно, в нем нужно найти адрес по маске (70|30) b5 [7-22] 01 24 [5-15] ff f7 ?? ?? (01 a8|08 a8|68 46) ff f7 [60-100] 01 24 ?? ?? ?? ?? (30|70) bd - незнаю на каком языке она написана но суть ее такова: первое число 70 или 30 (это начало адреса которое надо получить если вся маска совпадет), константа B5, в промежутке от седьмого байта до 22 искать 0124 (начало промежутка считается от предыдущего значения, в данном случае от B5), в промежутке от пятого байта до 15 искать FFF7 (в данном случае от 0124), любые два байта, одно из трех значений 01a8 или 08a8 или 6846, константа FFF7, в промежутке от 60-го байта до 100-го байта искать 0124(в данном случае ищем от FFF7), пропускаем 4 байта, 30 или 70, константа bd - если все совпадает то функция возвращает адрес (или количество байт от начала фаила до начала маски) начала поиска (в данном случае адрес до (70|30) B5), начал писать:
<autoit>
#include <Array.au3>

$File = FileOpen ( @ScriptDir & "\1.dat", 16 )
if $File = -1 Then
MsgBox (0,"Warning", "File not open")
EndIf
$sText = FileRead ($File)
MsgBox (0,"", $sText)
If StringRegExp($sText, '(70|30)B5') Then
MsgBox(0, 'флаг=0', 'Да, строка содержит маску')
Else
MsgBox(0, 'флаг=0', 'Нет такой строки')
EndIf </autoit>
и понял что не понимаю как мне искать в промежутке (как указано в схеме выше), подскажите пожалуйста как это делать или может я вообще не правильный путь выбрал?
PS
Извиняюсь если неправильно указал тег в котором должен быть заключен скрипт, просто у меня сейчас сайт отображается не так было раньше и нет кнопок для вставки этого кода.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Может быть так: Простой пример, есть строка ABBBBBBBBBB, где то после A может находиться цифра 5, но не дальше чем на 4 позиции от A
Значит подойдет такой паттерн: A.{0,4}5
После A, может быть что то, но не больше чем 4 раза, а затем обязательно должна идти 5

Вот возможные правильные:
A5BBBBBBBBBB
AB5BBBBBBBBB
ABB5BBBBBBBB
ABBB5BBBBBBB
ABBBB5BBBBBB
А эта уже не подойдет:
ABBBBB5BBBBB
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
inververs сказал(а):
Может быть так: Простой пример, есть строка ABBBBBBBBBB, где то после A может находиться цифра 5, но не дальше чем на 4 позиции от A
Значит подойдет такой паттерн: A.{0,4}5
После A, может быть что то, но не больше чем 4 раза, а затем обязательно должна идти 5

Вот возможные правильные:
A5BBBBBBBBBB
AB5BBBBBBBBB
ABB5BBBBBBBB
ABBB5BBBBBBB
ABBBB5BBBBBB
А эта уже не подойдет:
ABBBBB5BBBBB
Спасибо, за разжовувающий ответ, вопрос только тогда в знаке ".", если смотреть русскую справку то там сказано "Любой символ кроме переноса......", т.е. то что пишется в фигурных скобках относится к к тому что слева? В данном случае точке.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Да, если то что в фигурных скобках работало не к одному символу, а к нескольким - то можно объединить их в группу [что то тут] или в скобки (что то тут)
или если используете скобки, чисто ради группировки, то лучше писать так (?:что то тут)
Например, 2 точки, т.е два символа или байт, можно так записать: A(?:..){0,4}5


Добавлено:
Сообщение автоматически объединено:

Ваш случай: B5(?:..){6}(?:..){0,7}FF
Я ищу байт B5, потом должно идти ровно 6 любых байт (?:..){6}, затем мы можем пропустить до 7 байт (мы можем пропустить 0 байт, или 4), (?:..){0,7} но потом обязательно должна идти FF
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
Огромное спасибо! Еще один небольшой вопрос в догонку: не подскажете как еще мне получить адрес если данная маска верна, есть ли для этого функция или придется ее самому как то писать?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Оберните все в ()


Добавлено:
Сообщение автоматически объединено:

Да, еще обратите внимание что пробелы тоже учитываются. Их нужно удалить
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
inververs сказал(а):
Да, если то что в фигурных скобках работало не к одному символу, а к нескольким - то можно объединить их в группу [что то тут] или в скобки (что то тут)
или если используете скобки, чисто ради группировки, то лучше писать так (?:что то тут)
Например, 2 точки, т.е два символа или байт, можно так записать: A(?:..){0,4}5


Добавлено:
Сообщение автоматически объединено:

Ваш случай: B5(?:..){6}(?:..){0,7}FF
Я ищу байт B5, потом должно идти ровно 6 любых байт (?:..){6}, затем мы можем пропустить до 7 байт (мы можем пропустить 0 байт, или 4), (?:..){0,7} но потом обязательно должна идти FF



Попробовал вот так:
<autoit>
$File = FileOpen ( @ScriptDir & "\1.dat", 16 )
if $File = -1 Then
MsgBox (0,"Warning", "File not open")
EndIf
$sText = FileRead ($File)
If StringRegExp($sText, '(70|30)B5.{7-22}0124') Then
MsgBox(0, 'флаг=0', 'Да, строка содержит маску')
Else
MsgBox(0, 'флаг=0', 'Нет такой строки')
EndIf
</autoit>
выдает MSGbox "Нет такой строки", на картинке, что я приложил желтым помечено первое вхождение, а фиолетовым то самое 0124 которое находится в промежутке 7-22 байта от 70B5, я что то неправильно понял?
 

Вложения

  • 1.png
    1.png
    53.8 КБ · Просмотры: 9

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Так . это 1 символ. Отсчитайте от B5 22 символа, после них должна быть 01 24, а на картинке 28 14.
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
inververs сказал(а):
Так . это 1 символ. Отсчитайте от B5 22 символа, после них должна быть 01 24, а на картинке 28 14.
Извиняюсь я видать Вас запутал, 0124 должно быть в промежутке 7-22 байта, если брать по символам то это промежуток 14-44, я так понимаю такая маска (?:..) и должна обозначать 1 байт (т.е. 2 символа), попробовал так:
<autoit>StringRegExp($sText, '(70|30)B5(?:..){7}(?:..){0-15}0124') </autoit> т.е. как я понимаю: пропустить 7 байт (т.е. 14 символов) и в диапазоне от 0 до 15 байт (т.е. от 0 до 30 символов) искать 0124, но опять выдает ошибку =(
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
inververs сказал(а):
ну надо {0,15} а у вас минус
После Вашего сообщения вспомнилась фраза: "Шарик ты балбес", совсем запутался уже с символами =), но вот сейчас дошел до момента "или" где 3 значения, и почему то тоже не идет, хотя в самом начале использовал ту же форму
<autoit>StringRegExp($sText, '(70|30)B5(?:..){7}(?:..){0,15}0124(?:..){5}(?:..){0,10}FFF7(?:..){2}(01a8|08a8|6846)') </autoit> т.е. если посмотреть все тот же скрин выше, то видно что после FFF7 через 2 байта идет 08a8 что соответсвует маске, но почему то все равно ошибка =(, попробовал сделать так
<autoit> StringRegExp($sText, '(70|30)B5(?:..){7}(?:..){0,15}0124(?:..){5}(?:..){0,10}FFF7(?:..){2}(01|08|68) (a8|46)') </autoit> до (01|08|68) работает, а если добавляю (a8|46) то не работает =(
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
По картинке трудно ориентироваться. Киньте сюда кусок байтов
(01|08|68) (a8|46) и пробел между частями оставляете?
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
Надеюсь я Вас правильно понял (извиняюсь если нет): 70 B5 05 46 B0 F8 74 01 92 B0 0E 46 00 28 14 BF 01 24 00 24 00 20 8D F8 40 00 68 46 FF F7 26 FE 08 A8 FF F7 23 FE F4 B1 69 46 28 46 FF F7 B6 FF 20 BB 08 A9 28 46 FF F7 1C FE 04 00 1E D1 20 22 68 46 08 A9 5B F2 87 F7 00 28 14 BF 00 20 01 20 07 E0 25 32 58 00 03 00 04 00 90 9F 2D 21 1D 46 19 20 60 B9 0A E0 10 AA 31 46 28 46 FF F7 C6 FD 04 00 04 BF 9D F8 40 00 00 28 00 D0 01 24 12 B0 20 46 70 BD
красным выделил проблемное место, но мне приоритетней будет вариант (01 a8|08 a8|68 46) чем (01|08|68) (a8|46) т.к. 0146 например там быть не должно, его я попробовал чисто для проверки
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
ma:rofl:2007
Пробелы в паттерне учитываются, вам просто программа которой вы смотрите, их добавляет, что бы хоть как то было понятно, в файле же их нет, там все будет так
70B50546B0F8740192B0... смекаете?
Вот вы написали: (01 a8|08 a8|68 46), т.е найти 01 затем пробел затем a8


Добавлено:
Сообщение автоматически объединено:

попробуйте так: (?i)(70|30)B5(?:..){7}(?:..){0,15}0124(?:..){5}(?:..){0,10}FFF7(?:..){2}(01A8|08A8|6846)
 
Автор
M

maxd2007

Новичок
Сообщения
89
Репутация
0
inververs сказал(а):
ma:rofl:2007
Пробелы в паттерне учитываются, вам просто программа которой вы смотрите, их добавляет, что бы хоть как то было понятно, в файле же их нет, там все будет так
70B50546B0F8740192B0... смекаете?
Вот вы написали: (01 a8|08 a8|68 46), т.е найти 01 затем пробел затем a8


Добавлено:
Сообщение автоматически объединено:

попробуйте так: (?i)(70|30)B5(?:..){7}(?:..){0,15}0124(?:..){5}(?:..){0,10}FFF7(?:..){2}(01A8|08A8|6846)



На счет пробелов Вы правы, но я пробовал без них, проблема оказалась в регистре, я писал маленькие буквы (не обращая на это внимание, а там принципиально нужны были большие =)). Конечный результат таков <autoit>StringRegExp($sText, '(70|30)B5(?:..){7}(?:..){0,15}0124(?:..){5}(?:..){0,10}FFF7(?:..){2}(01A8|08A8|6846)')</autoit> Спасибо Вам еще раз!
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
А, ну может и регистр не тот, вот эта (?i) в начале позволяет писать в любом регистре )
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
ma:rofl:2007

Предупреждение За нарушение правил форума (пункт В.11):
Любые отрывки AutoIt кода необходимо заключать в тег [autoit]
autoit.gif
(подробнее), а обычный код соответственно в тег [code]
code.gif
(подробнее). Также большие выдержки текста помещайте под тег [spoiler]
spoiler.gif
(подробнее), там где это поддерживается естественно. Как в случае с названием темы, также короткое и эргономичное сообщение привлекает больше внимания, и шансы на получение конкретного ответа увеличиваются.


С уважением, ваш Глобальный модератор.
 
Верх