Dei uma resposta a essa pergunta, mas, ao ler novamente, acho que não a compreendi. Deseja converter cada 0x00um deles em um valor específico ou em um valor aleatório no 0x00-0xFFintervalo?
kos
11
@kos cada um para um valor específico, como 444444...não um acaso
Eduard Florinescu
Respostas:
18
O bashcódigo a seguir está definido para trabalhar com o byte sendo representado em binário . No entanto, você pode alterá-lo facilmente para lidar com ocatal , decimal ou hexadecimal , simplesmente alterando o valor da raizr de 2 para 8, 10ou 16respectivamente, e configurando de b=acordo.
EDIT - Ele lida com toda a gama de valores de bytes: hex 00 - FF (quando escrevi 00-7F abaixo, estava considerando apenas caracteres UTF-8 de byte único).
Se, por exemplo, você quiser apenas 4 bytes (caracteres no intervalo hex 00-7F somente UTF-8 'ASCII') , poderá inseri- lo na cabeça :... | head -c4
Saída (4 caracteres):
~~~~
Para ver a saída no formato de 8 bits, coloque-a em xxd(ou em qualquer outro despejo de bytes 1 e 0 *):
por exemplo. b=10000000e tubulação para:... | head -c4 | xxd -b
Você quis escrever o=$(printf ...)para a segunda linha?
jwodder
11
@jwodder: Não, a segunda linha está correta, como mostrado. A opção printf-v faz com que a saída defina diretamente a variável nomeada imediatamente após; neste caso, que o nome de variável é o(para octal ) - note que a -vopção se aplica ao shell-builtin versão printf(não o / usr / bin / printf versão)
Peter.O
2
@jwodder Além disso, em geral, a -vopção garante que a variável seja definida exatamente como você especificou. $(...)transforma a saída primeiro. É por isso o=$(printf '\n')que não terá o efeito que você poderia esperar, ao passo que printf -vo '\n'sim. (Não importa aqui, já que a saída aqui é de uma forma que não é afetado por essa transformação, mas se você não estavam cientes da -vopção, então isso pode ser útil para saber.)
HVD
18
Você não pode fazer isso facilmente.
Você pode escrever seu próprio módulo do kernel, fornecendo esse dispositivo. Eu não recomendo isso.
Você pode escrever um pequeno programa C escrevendo um fluxo infinito dos mesmos bytes em algum pipe (ou on stdout) ou FIFO.
Você pode usar tr (1) para ler /dev/zeroe traduzir cada 0 byte para outra coisa.
Você pode usar talvez sim (1) , pelo menos se puder pagar por novas linhas (ou então introduzi-lo em tr -d '\n'...)
@kojiro: isso falhará se você tentar yesum fluxo de \ncaracteres. Uma alternativa que lida com \né: yes '' | tr '\n' "$c"- onde $cpode haver qualquer caractere de toda a gama de caracteres ASCII.
Peter.O
11
@ Peter.O Não sei bem como você interpretou meu comentário como algo que não seja a expressão estática literal yes 1 | tr -d $'\n'. Suponho que você possa usar um shell que não faça o $''tratamento de barra invertida ou tentar encontrar um local que seja alterado tr -d $'\n', mas ainda não o encontrei.
Kojiro # 1155
@kojiro: Você yes 1 | tr -d $'\n'imprimirá com alegria um fluxo de 1caracteres e quase todos os outros valores de um byte, mas não pode imprimir um fluxo de \ncaracteres. O OP quer ser capaz de lidar com todos os valores de byte "entre 0x01 e 0xFF"
Peter.O
11
loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
PSKocik
13
Bem, se você literalmente deseja conseguir isso, pode usar um gancho LD_PRELOAD . A idéia básica é reescrever uma função da biblioteca C e usá-la em vez da normal.
Aqui está um exemplo simples em que substituímos a função read () para XOR o buffer de saída com 0x42.
Uma implementação ingênua XOR 0x42 em todos os arquivos que lemos, o que teria conseqüências indesejáveis. Para resolver esse problema, eu também instalei a função open () , fazendo com que ela buscasse o descritor de arquivo associado a / dev / zero. Então, apenas executamos o XOR em nossa função read () se fd == dev_zero_fd.
Dada a sua implementação, você pode ter um link simbólico de / dev / capbee para / dev / zero, procure por / dev / capbee e deixe / dev / zero sozinho. // dev / zero não será igual a / dev / zero.
Robert Jacobs
11
@RobertJacobs Indeed. Poderíamos até gerar links simbólicos / dev / 0x01, / dev / 0x02, / dev / 0x03, ... para / dev / zero e analisar o nome do arquivo para determinar a máscara de bit a ser aplicada.
yoann
11
Em termos de velocidade, o mais rápido que encontrei foi:
$ PERLIO=:unix perl -e '$s="\1" x 65536; for(;;){print $s}' | pv -a > /dev/null
[4.02GiB/s]
No meu Debian, perlrendimento 2.13GiB, enquanto < /dev/zerorendimento 8.73GiB. O que pode afetar o desempenho?
cuonglm
@ cuonglm, sim, vejo algumas variações entre os sistemas, mas perlé consistentemente mais rápido que as outras soluções. Eu obtenho a mesma taxa de transferência que com o programa C compilado equivalente. A referência é tanto no aplicativo quanto no agendador do sistema aqui. O que torna o mais diferente é o tamanho dos buffers que estão sendo gravados.
Stéphane Chazelas
@cuonglm O tubo também diminui a velocidade. Eu acho que cat /dev/zero| pv -a >/dev/nullvou lhe dar cerca de 2 GiBs por segundo (o que acontece no meu sistema, enquanto < /dev/zero) me dá cerca de 6GiBps.
PSKocik
@ StéphaneChazelas Posso perguntar em que sistema você está, Stéphane Chazelas? Os resultados no meu diferem bastante (posso obter cerca de 2.1GiB da versão perl). Estou no 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 por dentro.
PSKocik
11
@PSkocik, Linux 3.16.0-4-amd64 # 1 SMP Debian 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU / Linux, CPU Intel (R) Core (TM) 2 Duo T9600 a 2.80GHz. Um novo kernel parece fazer a diferença (a menos que os perl mais recentes: v5.20.2)
Stéphane Chazelas
7
É meio inútil tentar usar bitmask / x ou zero bytes, não é? Pegar um byte e xorzerá-lo é um no-op.
Basta criar um loop com os bytes desejados e colocá-lo atrás de um pipe ou pipe nomeado. Ele se comportará da mesma forma que um dispositivo de caractere (não desperdiçará ciclos de CPU quando ocioso):
mkfifo pipe
while : ; do echo -n "a"; done > pipe &
E se você quiser super otimizá-lo, pode usar o código C abaixo:
Originalmente, tentei usar o putchar em C, mas era lento.
PSKocik
Por curiosidade, por que em argc == 1+1vez deagrc == 2 ?
Reintegrar Monica iamnotmaynard
@iamnotmaynard Para lembrar a mim mesmo que é 1 para o executável da linha de comando mais 1 argumento. :-D
PSkocik
Ah Esse foi o meu palpite, mas queria ter certeza de que não havia nenhuma razão secreta.
Reintegrar Monica iamnotmaynard
"Pegar um byte e copiá-lo com zero é um no-op." Isso não é verdade:0 XOR X == X .
21415 Jacwah
5
Leia zeros, traduza cada zero para o seu padrão!
Lemos zero bytes de /dev/zeroe usamos trpara aplicar uma máscara de bit a cada um dos bytes, traduzindo cada byte de zero:
$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$
Octal 176 é o código ascii de ~, então obtemos 10 ~. (O $final da saída indica no meu shell que não havia final de linha - pode parecer diferente para você)
Então, vamos criar 0xFFbytes: Hex 0xFFé octal 0377. O zero à esquerda é deixado de fora para a trlinha de comando; No final, hexdumpé usado para tornar a saída legível.
Você precisa usar os códigos octais dos caracteres aqui, em vez do hexadecimal. Portanto, é o intervalo de\000 até octal \377(o mesmo que 0xFF).
Use ascii -xe ascii -opara obter uma tabela dos caracteres com números de índice hexadecimal ou octal.
(Para uma tabela com decimal e hexadecimal, apenas ascii).
Bem rápido
Ele roda bastante rápido, comparado ao uso de zeros: cat /dev/zeroé apenas quatro vezes mais rápido, enquanto pode fazer perfeito uso do buffer IO, quetr não pode.
$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]
$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]
Depende do que você deseja fazer com os dados e de quão flexível você deseja usá-los.
Na pior das hipóteses, se você precisar de velocidade, poderá fazer o mesmo que o / dev / zero e apenas compilar o / dev / one, / dev / two, .. / dev / fourtytwo .. e assim por diante.
Na maioria dos casos, deve ser melhor criar os dados diretamente onde são necessários, portanto, dentro de um programa / script como uma constante. Com mais informações, as pessoas poderiam ajudá-lo melhor.
0x00
um deles em um valor específico ou em um valor aleatório no0x00-0xFF
intervalo?444444...
não um acasoRespostas:
O
bash
código a seguir está definido para trabalhar com o byte sendo representado em binário . No entanto, você pode alterá-lo facilmente para lidar com ocatal , decimal ou hexadecimal , simplesmente alterando o valor da raizr
de2
para8
,10
ou16
respectivamente, e configurando deb=
acordo.EDIT - Ele lida com toda a gama de valores de bytes: hex 00 - FF (quando escrevi 00-7F abaixo, estava considerando apenas caracteres UTF-8 de byte único).
Se, por exemplo, você quiser apenas 4 bytes
(caracteres no intervalo hex 00-7F somente UTF-8 'ASCII'), poderáinseri-lo na cabeça :... | head -c4
Saída (4 caracteres):
Para ver a saída no formato de 8 bits, coloque-a em
xxd
(ou em qualquer outro despejo de bytes 1 e 0 *):por exemplo.
b=10000000
e tubulação para:... | head -c4 | xxd -b
fonte
o=$(printf ...)
para a segunda linha?-v
faz com que a saída defina diretamente a variável nomeada imediatamente após; neste caso, que o nome de variável éo
(para octal ) - note que a-v
opção se aplica ao shell-builtin versãoprintf
(não o / usr / bin / printf versão)-v
opção garante que a variável seja definida exatamente como você especificou.$(...)
transforma a saída primeiro. É por issoo=$(printf '\n')
que não terá o efeito que você poderia esperar, ao passo queprintf -vo '\n'
sim. (Não importa aqui, já que a saída aqui é de uma forma que não é afetado por essa transformação, mas se você não estavam cientes da-v
opção, então isso pode ser útil para saber.)Você não pode fazer isso facilmente.
Você pode escrever seu próprio módulo do kernel, fornecendo esse dispositivo. Eu não recomendo isso.
Você pode escrever um pequeno programa C escrevendo um fluxo infinito dos mesmos bytes em algum pipe (ou on
stdout
) ou FIFO.Você pode usar tr (1) para ler
/dev/zero
e traduzir cada 0 byte para outra coisa.Você pode usar talvez sim (1) , pelo menos se puder pagar por novas linhas (ou então introduzi-lo em
tr -d '\n'
...)fonte
yes 1 | tr -d $'\n'
para esse assunto.yes
um fluxo de\n
caracteres. Uma alternativa que lida com\n
é:yes '' | tr '\n' "$c"
- onde$c
pode haver qualquer caractere de toda a gama de caracteres ASCII.yes 1 | tr -d $'\n'
. Suponho que você possa usar um shell que não faça o$''
tratamento de barra invertida ou tentar encontrar um local que seja alteradotr -d $'\n'
, mas ainda não o encontrei.yes 1 | tr -d $'\n'
imprimirá com alegria um fluxo de1
caracteres e quase todos os outros valores de um byte, mas não pode imprimir um fluxo de\n
caracteres. O OP quer ser capaz de lidar com todos os valores de byte "entre 0x01 e 0xFF"loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
Bem, se você literalmente deseja conseguir isso, pode usar um gancho LD_PRELOAD . A idéia básica é reescrever uma função da biblioteca C e usá-la em vez da normal.
Aqui está um exemplo simples em que substituímos a função read () para XOR o buffer de saída com 0x42.
Uma implementação ingênua XOR 0x42 em todos os arquivos que lemos, o que teria conseqüências indesejáveis. Para resolver esse problema, eu também instalei a função open () , fazendo com que ela buscasse o descritor de arquivo associado a / dev / zero. Então, apenas executamos o XOR em nossa função read () se
fd == dev_zero_fd
.Uso:
fonte
Em termos de velocidade, o mais rápido que encontrei foi:
Para comparação:
fonte
perl
rendimento 2.13GiB, enquanto< /dev/zero
rendimento 8.73GiB. O que pode afetar o desempenho?perl
é consistentemente mais rápido que as outras soluções. Eu obtenho a mesma taxa de transferência que com o programa C compilado equivalente. A referência é tanto no aplicativo quanto no agendador do sistema aqui. O que torna o mais diferente é o tamanho dos buffers que estão sendo gravados.cat /dev/zero| pv -a >/dev/null
vou lhe dar cerca de 2 GiBs por segundo (o que acontece no meu sistema, enquanto< /dev/zero
) me dá cerca de 6GiBps.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 por dentro.É meio inútil tentar usar bitmask / x ou zero bytes, não é? Pegar um byte e
xor
zerá-lo é um no-op.Basta criar um loop com os bytes desejados e colocá-lo atrás de um pipe ou pipe nomeado. Ele se comportará da mesma forma que um dispositivo de caractere (não desperdiçará ciclos de CPU quando ocioso):
E se você quiser super otimizá-lo, pode usar o código C abaixo:
compilar e executar
Teste de performance:
2,1 GB / s na minha máquina (até um pouco mais rápido que
cat /dev/zero | pv -a >/dev/null
)fonte
argc == 1+1
vez deagrc == 2
?0 XOR X == X
.Leia zeros, traduza cada zero para o seu padrão!
Lemos zero bytes de
/dev/zero
e usamostr
para aplicar uma máscara de bit a cada um dos bytes, traduzindo cada byte de zero:Octal 176 é o código ascii de
~
, então obtemos 10~
. (O$
final da saída indica no meu shell que não havia final de linha - pode parecer diferente para você)Então, vamos criar
0xFF
bytes: Hex0xFF
é octal0377
. O zero à esquerda é deixado de fora para atr
linha de comando; No final,hexdump
é usado para tornar a saída legível.Você precisa usar os códigos octais dos caracteres aqui, em vez do hexadecimal. Portanto, é o intervalo de
\000
até octal\377
(o mesmo que0xFF
).Use
ascii -x
eascii -o
para obter uma tabela dos caracteres com números de índice hexadecimal ou octal.(Para uma tabela com decimal e hexadecimal, apenas
ascii
).Bem rápido
Ele roda bastante rápido, comparado ao uso de zeros:
cat /dev/zero
é apenas quatro vezes mais rápido, enquanto pode fazer perfeito uso do buffer IO, quetr
não pode.fonte
Depende do que você deseja fazer com os dados e de quão flexível você deseja usá-los.
Na pior das hipóteses, se você precisar de velocidade, poderá fazer o mesmo que o / dev / zero e apenas compilar o / dev / one, / dev / two, .. / dev / fourtytwo .. e assim por diante.
Na maioria dos casos, deve ser melhor criar os dados diretamente onde são necessários, portanto, dentro de um programa / script como uma constante. Com mais informações, as pessoas poderiam ajudá-lo melhor.
fonte
Infinte printf loop
Substitua
\u00
com o byte desejado.while true ; do printf "\u00" ; done | yourapp
Código C ++:
Compilar: substitua
Byte
pelo valor desejado.g++ -O3 -o bin file.cpp -D Byte=0x01
Usar
./bin | yourapp
fonte