Я дал ответ на этот вопрос, но читая его снова, я думаю, что я не понял его. Вы хотите перевести каждое из них 0x00к определенному значению или к случайному значению в 0x00-0xFFдиапазоне?
Кос
1
@kos каждый к определенному значению, как 444444...не случайному
Эдуард Флоринеску
Ответы:
18
Следующий bashкод настроен для работы с байтом, представленным в двоичном виде . Однако вы можете легко изменить его для обработки ocatal , десятичного или шестигранника , просто изменяя базисноеr значение 2 для 8, 10или , 16соответственно , и установки b=соответственно.
РЕДАКТИРОВАТЬ - Он обрабатывает полный диапазон значений байтов: hex 00 - FF (когда я писал ниже 00-7F, я рассматривал только однобайтовые символы UTF-8).
Если, например, вы хотите только 4 байта (символы в диапазоне UTF-8 «ASCII' только шестигранный 00-7F) , вы можете конвейеру в голову :... | head -c4
Выход (4 символа):
~~~~
Чтобы увидеть вывод в 8-битном формате, направьте его в xxd(или любой другой байтовый дамп 1 и 0 *):
например. b=10000000и трубопровод к:... | head -c4 | xxd -b
Вы хотели написать o=$(printf ...)для второй строки?
jwodder
1
@jwodder: Нет, вторая строка верна, как показано. Printf опция -vвызывает Лобовой выход непосредственно установить переменную сразу после него; в этом случае имя этой переменной o(для восьмеричного ) - обратите внимание, что этот -vпараметр применяется к встроенной в оболочку версии printf(не к версии / usr / bin / printf )
Peter.O
2
@jwodder Кроме того, в общем, -vопция гарантирует, что переменная будет установлена точно в соответствии с тем , что вы указали. $(...)сначала преобразует вывод. Вот почему o=$(printf '\n')не будет иметь эффекта, которого вы можете ожидать, в то время как printf -vo '\n'да. (Это не имеет значения, поскольку выходные данные представлены в форме, не подверженной такому преобразованию, но если вы не знали об этой -vопции, это может быть полезно знать.)
hvd
18
Вы не можете легко сделать это.
Вы можете написать свой собственный модуль ядра с таким устройством. Я не рекомендую это.
Вы можете написать крошечную C-программу, записывающую бесконечный поток одних и тех же байтов в какой-либо канал (или в stdout) или FIFO.
Вы можете использовать tr (1) для чтения /dev/zeroи перевода каждого 0 байта в другое.
Вы могли бы использовать, возможно, да (1) , по крайней мере, если вы можете позволить себе переводы строки (или еще трубку в tr -d '\n'...)
Или используйте yes 1 | tr -d $'\n'в этом отношении.
Кодзиро
3
@kojiro: это не удастся, если вы попытаетесь yesпоток \nсимволов. Альтернатива, которая обрабатывает \n: yes '' | tr '\n' "$c"- где $cможет быть любой символ из полного диапазона символов ASCII.
Peter.O
1
@ Peter.O Я не уверен, как вы интерпретировали мой комментарий, чтобы означать что-то кроме буквального, статического выражения yes 1 | tr -d $'\n'. Я полагаю, вы могли бы использовать оболочку, которая не выполняет $''обработку обратной косой черты, или вы можете попытаться найти локаль, которая изменяет tr -d $'\n', но я пока не нашел ее.
Кодзиро
@kojiro: Вы с yes 1 | tr -d $'\n'радостью напечатаете поток 1символов и почти все другие однобайтовые значения, но он не сможет напечатать поток \nсимволов. ОП хочет иметь возможность обрабатывать все байтовые значения «между 0x01 и 0xFF»
Peter.O
1
loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
PSkocik
13
Что ж, если вы в буквальном смысле хотите этого добиться, вы можете использовать ловушку LD_PRELOAD . Основная идея заключается в том, чтобы переписать функцию из библиотеки C и использовать ее вместо обычной.
Вот простой пример, где мы переопределяем функцию read () для XOR выходного буфера с 0x42.
Наивная реализация будет XOR 0x42 для каждого файла, который мы читаем, что будет иметь нежелательные последствия. Чтобы решить эту проблему, я также подключил функцию open () , заставив ее извлечь файловый дескриптор, связанный с / dev / zero. Тогда мы только выполняем XOR в нашей функции read (), если fd == dev_zero_fd.
Учитывая вашу реализацию, вы можете получить символическую ссылку от / dev / capbee до / dev / zero, выполнить поиск / dev / capbee и оставить / dev / zero в одиночку. // dev / zero не будет таким же, как / dev / zero.
Роберт Джейкобс
1
@RobertJacobs Действительно. Мы могли бы даже сгенерировать символические ссылки / dev / 0x01, / dev / 0x02, / dev / 0x03, ... в / dev / zero и проанализировать имя файла, чтобы определить применяемую битовую маску.
Йоан
11
С точки зрения скорости, самым быстрым, что я нашел, было:
$ PERLIO=:unix perl -e '$s="\1" x 65536; for(;;){print $s}' | pv -a > /dev/null
[4.02GiB/s]
В моем Debian вы perlполучите 2.13 ГБ, а < /dev/zero8.73 ГБ. Что может повлиять на производительность?
cuonglm
@cuonglm, да, я вижу некоторые различия между системами, но perlвсегда быстрее, чем другие решения. Я получаю ту же пропускную способность, что и с эквивалентной скомпилированной C-программой. Этот тест для приложения так же важен, как и для системного планировщика. Что отличает больше всего, так это размер записываемых буферов.
Стефан Шазелас
@cuonglm Труба тоже тормозит. Я думаю, cat /dev/zero| pv -a >/dev/nullчто даст вам около 2 ГиБ в секунду (это происходит в моей системе, в то время как < /dev/zero) дает мне около 6 ГБ / с.
PSkocik
@ StéphaneChazelas Могу я спросить, в какой ты системе, Стефан Шазелас? Результаты по моему весьма различны (я могу получить около 2,1 ГБ из Perl-версии). Я на Linux ProBook 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/LinuxIntel i5 Core внутри.
PSkocik
1
@PSkocik, Linux 3.16.0-4-amd64 # 1 SMP Debian 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU / Linux, процессор Intel® Core ™ 2 Duo T9600 @ 2.80 ГГц. Более новое ядро, кажется, имеет значение (если это не более новый perl: v5.20.2)
Стефан Шазелас
7
Бессмысленно пытаться использовать битовую маску / xor нулевых байтов, не так ли? Взять байт и xorзаписать его с нуля - нет.
Просто создайте цикл, который даст вам нужные байты, и поместите его за канал или именованный канал. Он будет вести себя почти так же, как символьное устройство (не будет тратить циклы ЦП во время простоя):
mkfifo pipe
while : ; do echo -n "a"; done > pipe &
И если вы хотите супероптимизировать его, вы можете использовать код C ниже:
Первоначально я пытался использовать putchar в C, но это было медленно.
PSkocik
Из любопытства, почему argc == 1+1вместо agrc == 2?
Восстановить Монику - Нотмайнард
@iamnotmaynard Чтобы напомнить себе, что это 1 для исполняемого файла командной строки плюс 1 аргумент. :-D
PSkocik
Ах. Это было мое предположение, но я хотел убедиться, что не было какой-то секретной причины.
Восстановить Монику - Нотмайнард
«Взятие байта и ксероксация его с нуля - неоправданно». Это не правда 0 XOR X == X.
Джеква
5
Читайте нули, переводите каждый ноль в ваш шаблон!
Мы читаем нулевые байты из /dev/zeroи используем, trчтобы применить битовую маску к каждому байту, переводя каждый нулевой байт:
$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$
Octal 176 - это код ascii ~, поэтому мы получаем 10 ~. (В $конце вывода указывает, что в моей оболочке не было конца строки - он может выглядеть по-другому для вас)
Итак, давайте создадим 0xFFбайты: Hex 0xFFявляется восьмеричным 0377. Ведущий ноль опущен для trкомандной строки; В конце hexdumpиспользуется, чтобы сделать вывод читабельным.
Вам нужно использовать восьмеричные коды символов здесь, а не шестнадцатеричные. Так что это диапазон от \000восьмеричного \377(так же, как 0xFF).
Используйте ascii -xи, ascii -oчтобы получить таблицу символов с шестнадцатеричным или восьмеричным индексными числами.
(Для таблицы с десятичной и шестнадцатеричной, просто ascii).
Довольно быстро
Он работает довольно быстро, по сравнению только с использованием нулей: cat /dev/zeroон всего в четыре раза быстрее, в то время как он может идеально использовать буферизацию ввода-вывода, что trневозможно.
$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]
$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]
Зависит от того, что вы хотите сделать с данными и насколько гибко вы хотите их использовать.
В худшем случае, если вам нужна скорость, вы можете сделать то же самое, что и / dev / zero, и просто скомпилировать / dev / one, / dev / two, .. / dev / fourtytwo .. и другие устройства.
В большинстве случаев лучше создавать данные непосредственно там, где это необходимо, то есть внутри программы / скрипта как константы. С большим количеством информации люди могли бы лучше помочь вам.
0x00
к определенному значению или к случайному значению в0x00-0xFF
диапазоне?444444...
не случайномуОтветы:
Следующий
bash
код настроен для работы с байтом, представленным в двоичном виде . Однако вы можете легко изменить его для обработки ocatal , десятичного или шестигранника , просто изменяя базисноеr
значение2
для8
,10
или ,16
соответственно , и установкиb=
соответственно.РЕДАКТИРОВАТЬ - Он обрабатывает полный диапазон значений байтов: hex 00 - FF (когда я писал ниже 00-7F, я рассматривал только однобайтовые символы UTF-8).
Если, например, вы хотите только 4 байта
(символы в диапазоне UTF-8 «ASCII' только шестигранный 00-7F), вы можете конвейеру в голову :... | head -c4
Выход (4 символа):
Чтобы увидеть вывод в 8-битном формате, направьте его в
xxd
(или любой другой байтовый дамп 1 и 0 *):например.
b=10000000
и трубопровод к:... | head -c4 | xxd -b
источник
o=$(printf ...)
для второй строки?-v
вызывает Лобовой выход непосредственно установить переменную сразу после него; в этом случае имя этой переменнойo
(для восьмеричного ) - обратите внимание, что этот-v
параметр применяется к встроенной в оболочку версииprintf
(не к версии / usr / bin / printf )-v
опция гарантирует, что переменная будет установлена точно в соответствии с тем , что вы указали.$(...)
сначала преобразует вывод. Вот почемуo=$(printf '\n')
не будет иметь эффекта, которого вы можете ожидать, в то время какprintf -vo '\n'
да. (Это не имеет значения, поскольку выходные данные представлены в форме, не подверженной такому преобразованию, но если вы не знали об этой-v
опции, это может быть полезно знать.)Вы не можете легко сделать это.
Вы можете написать свой собственный модуль ядра с таким устройством. Я не рекомендую это.
Вы можете написать крошечную C-программу, записывающую бесконечный поток одних и тех же байтов в какой-либо канал (или в
stdout
) или FIFO.Вы можете использовать tr (1) для чтения
/dev/zero
и перевода каждого 0 байта в другое.Вы могли бы использовать, возможно, да (1) , по крайней мере, если вы можете позволить себе переводы строки (или еще трубку в
tr -d '\n'
...)источник
yes 1 | tr -d $'\n'
в этом отношении.yes
поток\n
символов. Альтернатива, которая обрабатывает\n
:yes '' | tr '\n' "$c"
- где$c
может быть любой символ из полного диапазона символов ASCII.yes 1 | tr -d $'\n'
. Я полагаю, вы могли бы использовать оболочку, которая не выполняет$''
обработку обратной косой черты, или вы можете попытаться найти локаль, которая изменяетtr -d $'\n'
, но я пока не нашел ее.yes 1 | tr -d $'\n'
радостью напечатаете поток1
символов и почти все другие однобайтовые значения, но он не сможет напечатать поток\n
символов. ОП хочет иметь возможность обрабатывать все байтовые значения «между 0x01 и 0xFF»loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
Что ж, если вы в буквальном смысле хотите этого добиться, вы можете использовать ловушку LD_PRELOAD . Основная идея заключается в том, чтобы переписать функцию из библиотеки C и использовать ее вместо обычной.
Вот простой пример, где мы переопределяем функцию read () для XOR выходного буфера с 0x42.
Наивная реализация будет XOR 0x42 для каждого файла, который мы читаем, что будет иметь нежелательные последствия. Чтобы решить эту проблему, я также подключил функцию open () , заставив ее извлечь файловый дескриптор, связанный с / dev / zero. Тогда мы только выполняем XOR в нашей функции read (), если
fd == dev_zero_fd
.Использование:
источник
С точки зрения скорости, самым быстрым, что я нашел, было:
Для сравнения:
источник
perl
получите 2.13 ГБ, а< /dev/zero
8.73 ГБ. Что может повлиять на производительность?perl
всегда быстрее, чем другие решения. Я получаю ту же пропускную способность, что и с эквивалентной скомпилированной C-программой. Этот тест для приложения так же важен, как и для системного планировщика. Что отличает больше всего, так это размер записываемых буферов.cat /dev/zero| pv -a >/dev/null
что даст вам около 2 ГиБ в секунду (это происходит в моей системе, в то время как< /dev/zero
) дает мне около 6 ГБ / с.Linux ProBook 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Intel i5 Core внутри.Бессмысленно пытаться использовать битовую маску / xor нулевых байтов, не так ли? Взять байт и
xor
записать его с нуля - нет.Просто создайте цикл, который даст вам нужные байты, и поместите его за канал или именованный канал. Он будет вести себя почти так же, как символьное устройство (не будет тратить циклы ЦП во время простоя):
И если вы хотите супероптимизировать его, вы можете использовать код C ниже:
скомпилировать и запустить
Тест производительности:
2,1 ГБ / с на моей машине (даже немного быстрее, чем
cat /dev/zero | pv -a >/dev/null
)источник
argc == 1+1
вместоagrc == 2
?0 XOR X == X
.Читайте нули, переводите каждый ноль в ваш шаблон!
Мы читаем нулевые байты из
/dev/zero
и используем,tr
чтобы применить битовую маску к каждому байту, переводя каждый нулевой байт:Octal 176 - это код ascii
~
, поэтому мы получаем 10~
. (В$
конце вывода указывает, что в моей оболочке не было конца строки - он может выглядеть по-другому для вас)Итак, давайте создадим
0xFF
байты: Hex0xFF
является восьмеричным0377
. Ведущий ноль опущен дляtr
командной строки; В концеhexdump
используется, чтобы сделать вывод читабельным.Вам нужно использовать восьмеричные коды символов здесь, а не шестнадцатеричные. Так что это диапазон от
\000
восьмеричного\377
(так же, как0xFF
).Используйте
ascii -x
и,ascii -o
чтобы получить таблицу символов с шестнадцатеричным или восьмеричным индексными числами.(Для таблицы с десятичной и шестнадцатеричной, просто
ascii
).Довольно быстро
Он работает довольно быстро, по сравнению только с использованием нулей:
cat /dev/zero
он всего в четыре раза быстрее, в то время как он может идеально использовать буферизацию ввода-вывода, чтоtr
невозможно.источник
Зависит от того, что вы хотите сделать с данными и насколько гибко вы хотите их использовать.
В худшем случае, если вам нужна скорость, вы можете сделать то же самое, что и / dev / zero, и просто скомпилировать / dev / one, / dev / two, .. / dev / fourtytwo .. и другие устройства.
В большинстве случаев лучше создавать данные непосредственно там, где это необходимо, то есть внутри программы / скрипта как константы. С большим количеством информации люди могли бы лучше помочь вам.
источник
Infinte printf loop
Заменить
\u00
на байт, который вы хотите.while true ; do printf "\u00" ; done | yourapp
Код C ++:
Компилировать: заменить
Byte
на значение, которое вы хотите.g++ -O3 -o bin file.cpp -D Byte=0x01
использование
./bin | yourapp
источник