Как найти смещение шаблона из бинарного файла (без grep -b)

Я хочу получить байтовое смещение шаблона строки из двоичного файла на встроенной платформе Linux.

Если бы я мог использовать опцию «grep -b», это было бы лучшим способом, но она не поддерживается на моей машине.

Машина не поддерживает

ADDR=`grep -oba <pattern string> <file path> | cut -d ":" -f1`

Вот руководство по команде grep на машине.

root# grep --help

BusyBox v1.29.3 () multi-call binary.

Usage: grep \[-HhnlLoqvsriwFE\] \[-m N\] \[-A/B/C N\] PATTERN/-e PATTERN.../-f FILE \[FILE\]...

Search for PATTERN in FILEs (or stdin)

        -H      Add 'filename:' prefix
        -h      Do not add 'filename:' prefix
        -n      Add 'line_no:' prefix
        -l      Show only names of files that match
        -L      Show only names of files that don't match
        -c      Show only count of matching lines
        -o      Show only the matching part of line
        -q      Quiet. Return 0 if PATTERN is found, 1 otherwise
        -v      Select non-matching lines
        -s      Suppress open and read errors
        -r      Recurse
        -i      Ignore case
        -w      Match whole words only
        -x      Match whole lines only
        -F      PATTERN is a literal (not regexp)
        -E      PATTERN is an extended regexp
        -m N    Match up to N times per file
        -A N    Print N lines of trailing context
        -B N    Print N lines of leading context
        -C N    Same as '-A N -B N'
        -e PTRN Pattern to match
        -f FILE Read pattern from file

Так как этот вариант недоступен, я ищу альтернативу.

Комбинация hexdump и grep также может быть полезна

Такие как

ADDR=`hexdump <file path> -C | grep <pattern string> | cut -d' ' -f1`

Но если pattren занимает несколько строк, он не будет найден.

Есть ли способ найти смещение в байтах определенного шаблона с помощью команды Linux?

Кроме того, вероятно, избегайте верхнего регистра для имен ваших частных переменных и предпочитайте современный $(command substitution) синтаксис устаревшим обратным кавычкам.

tripleee 11.11.2022 09:50
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
0
1
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Что-то вроде этого?

hexdump -C "$file" |
awk -v pattern = "$pattern" 'residue { matched = ($0 ~ "\\|" residue) 
  if (matched) print $1; residue = ""; if (matched) next }
$0 ~ pattern { print $1 }
{ for(i=length(pattern)-1; i>0; i--)
  if ($0 ~ substr(pattern, 1, i) "\\|$") { residue=substr(pattern, i+1); break } }'

Смещение — это только первое поле из вывода hexdump; если вам нужно точное местоположение совпадения, это требует дополнительного массажа, чтобы выяснить смещение, которое нужно добавить к адресу, или вычесть, если оно было завернуто.

Кратко протестировано в чистом контейнере Busybox Docker, где вывод hexdump -C выглядит следующим образом:

/ # hexdump -C /etc/resolv.conf 
00000000  23 20 44 4e 53 20 72 65  71 75 65 73 74 73 20 61  |# DNS requests a|
00000010  72 65 20 66 6f 72 77 61  72 64 65 64 20 74 6f 20  |re forwarded to |
00000020  74 68 65 20 68 6f 73 74  2e 20 44 48 43 50 20 44  |the host. DHCP D|
00000030  4e 53 20 6f 70 74 69 6f  6e 73 20 61 72 65 20 69  |NS options are i|
00000040  67 6e 6f 72 65 64 2e 0a  6e 61 6d 65 73 65 72 76  |gnored..nameserv|
00000050  65 72 20 31 39 32 2e 31  36 38 2e 36 35 2e 35 0a  |er 192.168.65.5.|
00000060  20                                                | |

Пожалуйста, но, пожалуйста, не оставляйте комментарии «спасибо». Если вам что-то нравится, проголосуйте за это.

tripleee 11.11.2022 10:08
Ответ принят как подходящий

Установите шаблон в качестве разделителя записей в awk. Смещение вхождения равно длине первой записи. BusyBox awk обрабатывает RS как расширенное регулярное выражение, поэтому добавьте обратную косую черту перед любым из .[]\*+?^$ в строке шаблона.

<myfile.bin awk -v RS='pattern' '{print length($0); exit}'

Если шаблон содержит нулевой байт, вам потребуется немного дополнительной работы. Используйте tr для замены нулевых байтов некоторым значением байта, которое не отображается в шаблоне. Например, если шестнадцатеричный дамп шаблона равен 00002a61:

<myfile.bin tr '\0!' '!\0' | awk -v RS='!!-A' '{print length($0); exit}'

Если шаблон не найден, печатается длина всего файла. Поэтому, если вы не уверены, присутствует ли шаблон, вам снова потребуется дополнительная работа. Добавьте к файлу некоторый текст, который не может быть частью совпадения с шаблоном, чтобы вы знали, что если совпадение есть, оно не будет в самом конце файла. Тогда, если шаблон присутствует, файл будет содержать как минимум две записи. Но если шаблона нет, файл содержит только первую запись (без разделителя записей после нее).

{ cat myfile.bin; echo garbage; } |
awk -v RS='pattern' '
    NR==1 {n = length($0)}
    NR==2 {print n; found = 1; exit}
    END {exit !found}
'

Другие вопросы по теме