Как Вы пишете определенные байты в файл?

Когда regexp содержит группы, может быть больше чем один способ соответствовать строке против него: regexps с группами неоднозначны. Например, рассмотрите regexp ^.*\([0-9][0-9]*\)$ и строка a12. Существует две возможности:

  • Соответствие a против .* и 2 против [0-9]*; 1 подобран [0-9].
  • Соответствие a1 против .* и пустая строка против [0-9]*; 2 подобран [0-9].

Sed, как все другие regexp инструменты там, применяет самое раннее самое длинное правило соответствия: это сначала пытается соответствовать первой части переменной длины против строки, которая это максимально долго. Если это находит способ соответствовать остальной части строки против остальной части regexp, прекрасного. Иначе sed пробует следующее самое долгое соответствие за первую часть переменной длины и попробовал еще раз.

Здесь, соответствие с самой длинной строкой сначала a1 против .*, таким образом, группа только соответствует 2. Если Вы хотите, чтобы группа запустилась ранее, некоторые regexp механизмы позволяют Вам сделать .* менее жадный, но sed не имеет такой функции. Таким образом, необходимо удалить неоднозначность с некоторой дополнительной привязкой. Укажите что продвижение .* не может закончиться цифрой, так, чтобы первая цифра группы была первым возможным соответствием.

  • Если группа цифр не может быть в начале строки:

    sed -n 's/^.*[^0-9]\([0-9][0-9]*\).*/\1/p'
    
  • Если группа цифр может быть в начале строки, и Ваш sed поддерживает \? оператор для дополнительных частей:

    sed -n 's/^\(.*[^0-9]\)\?\([0-9][0-9]*\).*/\1/p'
    
  • Если группа цифр может быть в начале строки, придерживаясь стандарта regexp конструкции:

    sed -n -e 's/^.*[^0-9]\([0-9][0-9]*\).*/\1/p' -e t -e 's/^\([0-9][0-9]*\).*/\1/p'
    

Между прочим, именно то же самое самое раннее самое длинное правило соответствия делает [0-9]* соответствуйте цифрам после первой, а не последующего .*.

Обратите внимание, что, если существует несколько последовательностей цифр на строке, Ваша программа будет всегда извлекать последнюю последовательность цифр, снова из-за самого раннего самого долгого соответствия, правило относилось к начальной букве .*. Если Вы хотите извлечь первую последовательность цифр, необходимо указать, что то, что прибывает прежде, является последовательностью нецифр.

sed -n 's/^[^0-9]*\([0-9][0-9]*\).*$/\1/p'

В более общем плане, для извлечения первого соответствия regexp необходимо вычислить отрицание этого regexp. В то время как это всегда теоретически возможно, размер отрицания растет экспоненциально с размером regexp, который Вы инвертируете, таким образом, это часто непрактично.

Рассмотрите свой другой пример:

sed -n 's/.*\(CONFIG_[a-zA-Z0-9_]*\).*/\1/p'

Этот пример на самом деле показывает ту же проблему, но Вы не видите его на типичных исходных данных. Если Вы подаете его hello CONFIG_FOO_CONFIG_BAR, затем команда выше распечатывает CONFIG_BAR, нет CONFIG_FOO_CONFIG_BAR.

Существует способ распечатать первое соответствие с sed, но это немного хитро:

sed -n -e 's/\(CONFIG_[a-zA-Z0-9_]*\).*/\n\1/' -e T -e 's/^.*\n//' -e p

(Принятие Ваших поддержек sed \n означать новую строку в s текст замены.) Это работает, потому что sed ищет самое раннее соответствие regexp, и мы не пытаемся соответствовать тому, что предшествует CONFIG_… бит. С тех пор нет никакой новой строки в строке, мы можем использовать ее в качестве временного маркера. T команда говорит, чтобы сдаться если предыдущее s команда не соответствовала.

Когда Вы не можете выяснить, как сделать что-то в sed, обратиться к awk. Следующая команда печатает самое раннее самое долгое соответствие regexp:

awk 'match($0, /[0-9]+/) {print substr($0, RSTART, RLENGTH)}'

И если Вы испытываете желание сохранять это простым, используйте Perl.

perl -l -ne '/[0-9]+/ && print $&'       # first match
perl -l -ne '/^.*([0-9]+)/ && print $1'  # last match
6
12.03.2015, 22:09
6 ответов

Это hexundump сценарий от моего персонального набора:

#!/usr/bin/env perl
$^W = 1;
$c = undef;
while (<>) {
    tr/0-9A-Fa-f//cd;
    if (defined $c) { warn "Consuming $c"; $_ = $c . $_; $c = undef; }
    if (length($_) & 1) { s/(.)$//; $c = $1; }
    print pack "H*", $_;
}
if (!eof) { die "$!"; }
if (defined $c) { warn "Odd number of hexadecimal digits"; }
6
27.01.2020, 20:21

Моделируйте поезд байта:

echo 41 42 43 44 | 

Изменение располагает с интервалами в новые строки так, в то время как/чтение может легко проанализировать их на одним

tr ' ' '\n' | 

Байт синтаксического анализа байтом

while read hex; do

Преобразуйте шестнадцатеричное число в ASCII:

  printf \\x$hex

до конца входа

done

Если файлы для парсинга являются серьезно большими, Вы, вероятно, не хотите использовать удар, потому что это медленно. Perl, например, был бы лучшим выбором.

3
27.01.2020, 20:21

Можно использовать echo -e:

echo -e "\x66\x6f\x6f"

Действительно отметьте это hexdump -C то, что Вы хотите вывести содержание файла в порядке байтов вместо того, чтобы быть интерпретированными как 4-байтовые слова в сетевом порядке байтов.

6
27.01.2020, 20:21
  • 1
    Хотя это действительно отвечает на мой вопрос, он не помогает в моей ситуации. У меня есть очень большой вход шестнадцатеричных чисел, которые я хотел бы передать по каналу в файл. Я обновлю вопрос с этим. –  Cory Klein 15.11.2012, 01:40

*some_utility* Вы находите, dd (руководство). Можно скопировать любые допустимые байты с любого допустимого положения файла в другой файл, указывают bs(размер блока), count, и skip опции.

Пример

Скопируйте первые 1 024 байта файла в другой файл.

$ dd if=liveusb-creator-3.11.7-setup.exe of=test.ex_ bs=1 count=1024
1024+0 records in
1024+0 records out
1024 bytes (1.0 kB) copied, 0.03922 s, 26.1 kB/s
1
27.01.2020, 20:21

Вот пример того, как вы можете использовать DC на p Rint (uchar_max + 1) значение байта :

printf %dP 104 101 121 32 116 104 101 114 101 10 |dc

... какие печатает ...

hey there

Уэл. I RADIX NUPTIX 10 - Десятичная - но вы можете установить его с $ val I , где $ val - это любое число от 2 до 16 (обратите внимание, что если текущий входной Radix не 10, вам придется использовать значение текущей базы для 10, чтобы вернуть его - иначе вы всегда можете сделать АИ ) .

Вот более сложный пример:

LC_ALL=C man man 2>/dev/null | 
od -v -An -t x1 |
tr -s '[:space:]' P | {
    echo 16i0
    tr '[:lower:]' '[:upper:]'
} | dc | head

... который переводится человек человек вывод в шестнадцатеричные и обратно снова в потоке и печатаю:

MAN(1)              Manual pager utils              MAN(1)



NAME
       man - an interface to the on-line reference manuals

SYNOPSIS
       man [-C file] [-d] [-D] [--warnings[=warnings]] [-R
       encoding] [-L locale] [-m system[,...]]  [-M  path]

Просто убедитесь, что весь ваш алфавит [: ШестнадцатеричнаяЦифра:] ы являются заглавными буквами и сэндвич P между каждой парой, то труба его в постоянного тока .

1
27.01.2020, 20:21

Для записи произвольных шестнадцатеричных данных в двоичный файл:

echo -n 666f6f | xxd -r -p - file.bin

Для шестнадцатеричного ввода ()данные, хранящиеся в некотором файле, должны быть записаны в двоичный файл:

xxd -r -p file.hex file.bin

Чтение двоичных данных:
hd file.binилиxxd file.bin

Чтение только данных (без смещений):

xxd -p file.bin
1
29.01.2021, 02:17

Теги

Похожие вопросы