Di una respuesta a esta pregunta, pero al leerla nuevamente creo que la entendí mal. ¿Desea traducir cada uno 0x00a un valor específico o a un valor aleatorio en el 0x00-0xFFrango?
kos
1
@kos cada uno a un valor específico como 444444...no aleatorio
Eduard Florinescu
Respuestas:
18
El siguiente bashcódigo está configurado para funcionar con el byte representado en binario . Sin embargo, puede cambiarlo fácilmente para manejar ocatal , decimal o hexadecimal simplemente cambiando el valor de la raízr de 2 a 8, 10o 16respectivamente, y configurándolo en b=consecuencia.
EDITAR : maneja el rango completo de valores de bytes: hexadecimal 00 - FF (cuando escribí 00-7F a continuación, estaba considerando solo caracteres UTF-8 de un solo byte).
Si, por ejemplo, solo desea 4 bytes (caracteres en el rango UTF-8 'ASCII'-hexadecimal solo 00-7F) , puede canalizarlo a la cabeza :... | head -c4
Salida (4 caracteres):
~~~~
Para ver la salida en formato de 8 bits, canalícela xxd(o cualquier otro volcado de byte de 1 y 0 *):
por ejemplo. b=10000000y tuberías a:... | head -c4 | xxd -b
¿Querías escribir o=$(printf ...)para la segunda línea?
jwodder
1
@jwodder: No, la segunda línea es correcta como se muestra. La opción printf-v hace que la salida establezca directamente la variable nombrada inmediatamente después de ella; en este caso, el nombre de la variable es o(para octal ): tenga en cuenta que la -vopción se aplica a la versión integrada de shell de printf(no a la versión / usr / bin / printf )
Peter.O
2
@jwodder Además, en general, la -vopción se asegura de que la variable se configure exactamente a lo que especificó. $(...)transforma la salida primero. Es por eso o=$(printf '\n')que no tendrá el efecto que podría esperar, mientras que printf -vo '\n'sí. (No importa aquí, ya que la salida aquí está en una forma que no se ve afectada por tal transformación, pero si no -vconocía la opción, entonces podría ser útil saberlo).
hvd
18
No puedes hacer eso fácilmente.
Puede considerar escribir su propio módulo de kernel que proporcione dicho dispositivo. No lo recomiendo
Podría escribir un pequeño programa en C escribiendo una secuencia infinita de los mismos bytes en alguna tubería (o en stdout) o FIFO.
Puede usar tr (1) para leer /dev/zeroy traducir cada byte 0 a otra cosa.
Podría usar quizás sí (1) , al menos si puede permitirse el lujo de tener nuevas líneas (o de lo contrario canalizarlas en tr -d '\n'...)
@kojiro: eso fallará si intentas yesuna secuencia de \ncaracteres. Una alternativa que maneja \nes: yes '' | tr '\n' "$c"- donde $cpuede haber cualquier carácter de la gama completa de caracteres ASCII.
Peter.O
1
@ Peter.O No estoy seguro de cómo interpretaste mi comentario como algo que no sea la expresión literal y estática yes 1 | tr -d $'\n'. Supongo que podría usar un shell que no haga el $''tratamiento de barra invertida, o podría tratar de encontrar un lugar que altere tr -d $'\n', pero aún no lo he encontrado.
kojiro
@kojiro: yes 1 | tr -d $'\n'con bastante gusto imprimirá una secuencia de 1caracteres y casi cualquier otro valor de un solo byte, pero no puede imprimir una secuencia de \ncaracteres. El OP quiere poder manejar todos los valores de bytes "entre 0x01 y 0xFF"
Peter.O
1
loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
PSkocik
13
Bueno, si literalmente quieres lograr esto, puedes usar un gancho LD_PRELOAD . La idea básica es reescribir una función de la biblioteca C y usarla en lugar de la normal.
Aquí hay un ejemplo simple donde anulamos la función read () para XOR el buffer de salida con 0x42.
Una implementación ingenua haría XOR 0x42 en cada archivo que leamos, lo que tendría consecuencias indeseables. Para resolver este problema, también conecté la función open () , haciendo que recupere el descriptor de archivo asociado con / dev / zero. Entonces, solo realizamos el XOR en nuestra función read () si fd == dev_zero_fd.
Dada su implementación, podría tener un enlace simbólico de / dev / capbee a / dev / zero, busque / dev / capbee y deje / dev / zero solo. // dev / zero no será lo mismo que / dev / zero.
Robert Jacobs
1
@RobertJacobs De hecho. Incluso podríamos generar enlaces simbólicos / dev / 0x01, / dev / 0x02, / dev / 0x03, ... a / dev / zero y analizar el nombre de archivo para determinar la máscara de bits que se aplicará.
yoann
11
En términos de velocidad, lo más rápido que encontré fue:
$ PERLIO=:unix perl -e '$s="\1" x 65536; for(;;){print $s}' | pv -a > /dev/null
[4.02GiB/s]
En mi Debian, perlrendimiento 2.13GiB, mientras que < /dev/zerorendimiento 8.73GiB. ¿Qué cosa puede afectar el rendimiento?
Cuonglm
@cuonglm, sí, veo alguna variación entre sistemas, pero perles consistentemente más rápido que las otras soluciones. Obtengo el mismo rendimiento que con el programa C compilado equivalente. El punto de referencia está tanto en la aplicación como en el programador del sistema aquí. Lo que hace más diferente es el tamaño de los buffers que se escriben.
Stéphane Chazelas
@cuonglm La tubería también lo ralentiza. Creo que también cat /dev/zero| pv -a >/dev/nullle dará unos 2 GiB por segundo (lo hace en mi sistema, mientras que < /dev/zero) me da alrededor de 6GiBps.
PSkocik
@ StéphaneChazelas ¿Puedo preguntar en qué sistema estás, Stéphane Chazelas? Los resultados en los míos difieren bastante (puedo obtener aproximadamente 2.1GiB de la versión perl). Estoy en 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
1
@PSkocik, Linux 3.16.0-4-amd64 # 1 SMP Debian 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU / Linux, Intel (R) Core (TM) 2 Duo CPU T9600 @ 2.80GHz. El kernel más nuevo parece marcar la diferencia (a menos que sea el perl más nuevo: v5.20.2)
Stéphane Chazelas
7
Es un poco inútil tratar de poner una máscara de bits / x o cero bytes, ¿no? Tomar un byte y xorponerlo en cero es un no-op.
Simplemente cree un bucle que le brinde los bytes que desea y póngalo detrás de una tubería o una tubería con nombre. Se comportará más o menos igual que un dispositivo de caracteres (no desperdiciará los ciclos de la CPU cuando esté inactivo):
mkfifo pipe
while : ; do echo -n "a"; done > pipe &
Y si desea super-optimizarlo, puede usar el siguiente código C:
Originalmente intenté usar putchar en C, pero fue lento.
PSkocik
Por curiosidad, ¿por qué en argc == 1+1lugar de agrc == 2?
Restablece a Monica - notmaynard el
@iamnotmaynard Para recordarme que es 1 para el ejecutable de línea de comando más 1 argumento. :-D
PSkocik
Ah Esa era mi suposición, pero quería asegurarme de que no hubiera alguna razón secreta.
Restablece a Monica - notmaynard el
"Tomar un byte y modificarlo con cero es un no-op". Esto no es cierto: 0 XOR X == X.
jacwah
5
¡Lee ceros, traduce cada cero a tu patrón!
Leemos cero bytes /dev/zeroy usamos trpara aplicar una máscara de bits a cada uno de los bytes traduciendo cada byte cero:
$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$
Octal 176 es el código ascii de ~, por lo que obtenemos 10 ~. (Al $final de la salida indica en mi shell que no había final de línea, podría verse diferente para usted)
Entonces, creemos 0xFFbytes: Hex 0xFFes octal 0377. El cero inicial se deja fuera de la trlínea de comando; Al final, hexdumpse utiliza para hacer que la salida sea legible.
Debe usar los códigos octales de los caracteres aquí, en lugar del hexadecimal. Entonces es el rango de \000octal \377(igual que 0xFF).
Use ascii -xy ascii -opara obtener una tabla de los caracteres con números de índice hexadecimales u octales.
(Para una tabla con decimal y hexadecimal, solo ascii).
Bastante rapido
Funciona bastante rápido, en comparación con solo usar los ceros: cat /dev/zeroes solo cuatro veces más rápido, mientras que puede hacer un uso perfecto del almacenamiento en búfer IO, que trno puede.
$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]
$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]
Depende de lo que quiera hacer con los datos y de cuán flexible quiera usarlos.
En el peor de los casos, si necesita velocidad, podría hacer lo mismo que / dev / zero, y simplemente compilar los dispositivos / dev / one, / dev / two, .. / dev / fourtytwo .. y así sucesivamente.
En la mayoría de los casos, debería ser mejor crear los datos directamente donde se necesitan, por lo que dentro de un programa / script como una constante. Con más información, la gente podría ayudarlo mejor.
0x00
a un valor específico o a un valor aleatorio en el0x00-0xFF
rango?444444...
no aleatorioRespuestas:
El siguiente
bash
código está configurado para funcionar con el byte representado en binario . Sin embargo, puede cambiarlo fácilmente para manejar ocatal , decimal o hexadecimal simplemente cambiando el valor de la raízr
de2
a8
,10
o16
respectivamente, y configurándolo enb=
consecuencia.EDITAR : maneja el rango completo de valores de bytes: hexadecimal 00 - FF (cuando escribí 00-7F a continuación, estaba considerando solo caracteres UTF-8 de un solo byte).
Si, por ejemplo, solo desea 4 bytes
(caracteres en el rango UTF-8 'ASCII'-hexadecimal solo 00-7F), puede canalizarlo a la cabeza :... | head -c4
Salida (4 caracteres):
Para ver la salida en formato de 8 bits, canalícela
xxd
(o cualquier otro volcado de byte de 1 y 0 *):por ejemplo.
b=10000000
y tuberías a:... | head -c4 | xxd -b
fuente
o=$(printf ...)
para la segunda línea?-v
hace que la salida establezca directamente la variable nombrada inmediatamente después de ella; en este caso, el nombre de la variable eso
(para octal ): tenga en cuenta que la-v
opción se aplica a la versión integrada de shell deprintf
(no a la versión / usr / bin / printf )-v
opción se asegura de que la variable se configure exactamente a lo que especificó.$(...)
transforma la salida primero. Es por esoo=$(printf '\n')
que no tendrá el efecto que podría esperar, mientras queprintf -vo '\n'
sí. (No importa aquí, ya que la salida aquí está en una forma que no se ve afectada por tal transformación, pero si no-v
conocía la opción, entonces podría ser útil saberlo).No puedes hacer eso fácilmente.
Puede considerar escribir su propio módulo de kernel que proporcione dicho dispositivo. No lo recomiendo
Podría escribir un pequeño programa en C escribiendo una secuencia infinita de los mismos bytes en alguna tubería (o en
stdout
) o FIFO.Puede usar tr (1) para leer
/dev/zero
y traducir cada byte 0 a otra cosa.Podría usar quizás sí (1) , al menos si puede permitirse el lujo de tener nuevas líneas (o de lo contrario canalizarlas en
tr -d '\n'
...)fuente
yes 1 | tr -d $'\n'
para el caso.yes
una secuencia de\n
caracteres. Una alternativa que maneja\n
es:yes '' | tr '\n' "$c"
- donde$c
puede haber cualquier carácter de la gama completa de caracteres ASCII.yes 1 | tr -d $'\n'
. Supongo que podría usar un shell que no haga el$''
tratamiento de barra invertida, o podría tratar de encontrar un lugar que alteretr -d $'\n'
, pero aún no lo he encontrado.yes 1 | tr -d $'\n'
con bastante gusto imprimirá una secuencia de1
caracteres y casi cualquier otro valor de un solo byte, pero no puede imprimir una secuencia de\n
caracteres. El OP quiere poder manejar todos los valores de bytes "entre 0x01 y 0xFF"loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
Bueno, si literalmente quieres lograr esto, puedes usar un gancho LD_PRELOAD . La idea básica es reescribir una función de la biblioteca C y usarla en lugar de la normal.
Aquí hay un ejemplo simple donde anulamos la función read () para XOR el buffer de salida con 0x42.
Una implementación ingenua haría XOR 0x42 en cada archivo que leamos, lo que tendría consecuencias indeseables. Para resolver este problema, también conecté la función open () , haciendo que recupere el descriptor de archivo asociado con / dev / zero. Entonces, solo realizamos el XOR en nuestra función read () si
fd == dev_zero_fd
.Uso:
fuente
En términos de velocidad, lo más rápido que encontré fue:
Para comparacion:
fuente
perl
rendimiento 2.13GiB, mientras que< /dev/zero
rendimiento 8.73GiB. ¿Qué cosa puede afectar el rendimiento?perl
es consistentemente más rápido que las otras soluciones. Obtengo el mismo rendimiento que con el programa C compilado equivalente. El punto de referencia está tanto en la aplicación como en el programador del sistema aquí. Lo que hace más diferente es el tamaño de los buffers que se escriben.cat /dev/zero| pv -a >/dev/null
le dará unos 2 GiB por segundo (lo hace en mi sistema, mientras que< /dev/zero
) me da alrededor 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.Es un poco inútil tratar de poner una máscara de bits / x o cero bytes, ¿no? Tomar un byte y
xor
ponerlo en cero es un no-op.Simplemente cree un bucle que le brinde los bytes que desea y póngalo detrás de una tubería o una tubería con nombre. Se comportará más o menos igual que un dispositivo de caracteres (no desperdiciará los ciclos de la CPU cuando esté inactivo):
Y si desea super-optimizarlo, puede usar el siguiente código C:
compilar y ejecutar
Prueba de rendimiento:
2.1GB / s en mi máquina (incluso un poco más rápido que
cat /dev/zero | pv -a >/dev/null
)fuente
argc == 1+1
lugar deagrc == 2
?0 XOR X == X
.¡Lee ceros, traduce cada cero a tu patrón!
Leemos cero bytes
/dev/zero
y usamostr
para aplicar una máscara de bits a cada uno de los bytes traduciendo cada byte cero:Octal 176 es el código ascii de
~
, por lo que obtenemos 10~
. (Al$
final de la salida indica en mi shell que no había final de línea, podría verse diferente para usted)Entonces, creemos
0xFF
bytes: Hex0xFF
es octal0377
. El cero inicial se deja fuera de latr
línea de comando; Al final,hexdump
se utiliza para hacer que la salida sea legible.Debe usar los códigos octales de los caracteres aquí, en lugar del hexadecimal. Entonces es el rango de
\000
octal\377
(igual que0xFF
).Use
ascii -x
yascii -o
para obtener una tabla de los caracteres con números de índice hexadecimales u octales.(Para una tabla con decimal y hexadecimal, solo
ascii
).Bastante rapido
Funciona bastante rápido, en comparación con solo usar los ceros:
cat /dev/zero
es solo cuatro veces más rápido, mientras que puede hacer un uso perfecto del almacenamiento en búfer IO, quetr
no puede.fuente
Depende de lo que quiera hacer con los datos y de cuán flexible quiera usarlos.
En el peor de los casos, si necesita velocidad, podría hacer lo mismo que / dev / zero, y simplemente compilar los dispositivos / dev / one, / dev / two, .. / dev / fourtytwo .. y así sucesivamente.
En la mayoría de los casos, debería ser mejor crear los datos directamente donde se necesitan, por lo que dentro de un programa / script como una constante. Con más información, la gente podría ayudarlo mejor.
fuente
Bucle de impresión infinito
Reemplace
\u00
con el byte que desee.while true ; do printf "\u00" ; done | yourapp
Código C ++:
Compilar: reemplace
Byte
con el valor que desee.g++ -O3 -o bin file.cpp -D Byte=0x01
Utilizar
./bin | yourapp
fuente