GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo puedo convertir datos de texto de dos valores a binario (representación de bits)?

Otra perlita:

perl -pe 'BEGIN { binmode \*STDOUT } chomp; tr/AB/\0\1/; $_ = pack "B*", $_'

Prueba:

$ echo ABBBAAAABBBBBABBABBBABBB | \
    perl -pe 'BEGIN { binmode \*STDOUT } chomp; tr/AB/\0\1/; $_ = pack "B*", $_' | \
    od -tx1
0000000 70 fb 77
0000003

Lo anterior lee la entrada una línea a la vez. Depende de usted asegurarse de que las líneas sean exactamente lo que se supone que deben ser.

Editar: La operación inversa:

#!/usr/bin/env perl

binmode \*STDIN;

while ( defined ( $_ = getc ) ) {
    $_ = unpack "B*";
    tr/01/AB/;
    print;
    print "\n" if ( not ++$cnt % 3 );
}
print "\n" if ( $cnt % 3 );

Esto lee un byte de entrada a la vez.

Edición 2: Operación inversa más simple:

perl -pe 'BEGIN { $/ = \3; $\ = "\n"; binmode \*STDIN } $_ = unpack "B*"; tr/01/AB/'

Lo anterior lee 3 bytes a la vez desde STDIN (pero recibiendo EOF en medio de una secuencia no es un problema fatal).


{   printf '2i[q]sq[?z0=qPl?x]s?l?x'
    tr -dc AB | tr AB 01 | fold -b24
}   <infile   | dc

Al hacer la siguiente declaración, @lcd047 ha dado en el clavo con mi anterior estado de confusión:

Pareces estar confundido por la salida de od . Usa od -tx1 para mirar bytes. od -x lee palabras, y en máquinas little endian que intercambian bytes. No seguí de cerca el intercambio anterior, pero creo que su versión inicial era correcta y no necesita meterse con el orden de bytes en absoluto. Solo usa od -tx1 , no od -x .

Ahora bien, esto me hace sentir mucho mucho mejor:la necesidad anterior de dd conv=swab me estuvo molestando todo el día. No pude fijarlo, pero sabía que había algo mal con él. Poder explicarlo con mi propia estupidez es muy reconfortante, especialmente porque aprendí algo.

De todos modos, eso eliminará todos los bytes que no sean [AB] , luego tr traducirlos a [01] en consecuencia, antes de fold ing el flujo resultante a 24 bytes por línea. dc ? lee una línea a la vez, verifica si la entrada contenía algo y, si es así, P imprime el valor en bytes de ese número en la salida estándar.

Desde man dc :

  • P

    • Extrae el valor en la parte superior de la pila. Si es una cadena, simplemente se imprime sin una nueva línea al final. De lo contrario, es un número, y la parte entera de su valor absoluto se imprime como una base "(UCHAR_MAX+1 )" flujo de bytes
  • i

    • Retira el valor de la parte superior de la pila y lo usa para establecer la base de entrada.

algo de automatización de shell

Aquí hay una función de shell que escribí basada en lo anterior que puede funcionar en ambos sentidos:

ABdc()( HOME=/dev/null  A='[fc[fc]]sp[100000000o]p2o[fc]' B=2i
        case    $1      in
        (-B) {  echo "$B"; tr AB 01      | paste -dP - ~      ; }| dc;;
        (-A) {  echo "$A"; od -vAn -tu1  | paste -dlpx - ~ ~ ~; }| dc|
         dc  |  paste - - - ~            | expand -t10,20,30     |
                cut -c2-9,12-19,22-29    | tr ' 01' AAB         ;;
        (*)     set '' "$1";: ${1:?Invalid opt: "'$2'"}         ;;
        esac
)

Eso traducirá el ABABABA cosas a bytes con -B , así que solo puedes hacer:

ABdc -B <infile

Pero traducirá la entrada arbitraria a 24 ABABABA cadenas codificadas bit por byte, en la misma forma que se presenta, por ejemplo, en la pregunta, con -B .

seq 5 | ABdc -A | tee /dev/fd/2 | ABdc -B

AABBAAABAAAABABAAABBAABA
AAAABABAAABBAABBAAAABABA
AABBABAAAAAABABAAABBABAB
AAAABABAAAAAAAAAAAAAAAAA
1
2
3
4
5

Para -A salida que rodé en cut , expand y od aquí, que abordaré en un minuto, pero también agregué otro dc . Dejé caer la línea por línea ? leer dc secuencia de comandos para otro método que trabaja una matriz a la vez con f - que es un comando que imprime el f completo dc pila de comandos a la salida estándar. Por supuesto, porque dc es un último en entrar, primero en salir orientado a la pila tipo de aplicación, eso significa que el f ull-stack sale en el orden inverso al que entró.

Esto podría ser un problema, pero uso otro dc de todos modos con un o base de salida establecida en 100000000 para manejar todo el relleno 0 de la manera más simple posible. Y cuando lee el último en entrar, primero en salir del otro flujo, aplica esa lógica a todo de nuevo, y todo sale en el lavado. Los dos dc s trabajar en concierto como este:

{   echo '[fc[fc]]sp[100000000o]p2o[fc]'
    echo some data | 
    od -An -tu1        ###arbitrary input to unsigned decimal ints
    echo lpx           ###load macro stored in p and execute
} | tee /dev/fd/2  |   ###just using tee to show stream stages
dc| tee /dev/fd/2  |dc 

...la transmisión según el primer tee ...

[fc[fc]]sp[100000000o]pc2o[fc]            ###dc's init cmd from 1st echo
 115 111 109 101  32 100  97 116  97  10  ###od's output
lpx                                       ###load p; execute

...por el segundo tee , como está escrito desde dc a dc ...

100000000o                             ###first set output radix
1010                                   ###bin/rev vs of od's out
1100001                                ###dc #2 reads it in, revs and pads it 
1110100                                
1100001
1100100
100000
1100101
1101101
1101111                                ###this whole process is repeated
1110011                                ###once per od output line, so
fc                                     ###each worked array is 16 bytes.

...y la salida que el segundo dc escribe es...

 01110011
 01101111
 01101101
 01100101
 00100000
 01100100
 01100001
 01110100
 01100001
 00001010

A partir de ahí la función paste está en ...

 01110011    01101111    01101101
 01100101    00100000    01100100
 01100001    01110100    01100001
 00001010

...expand s a espacios en intervalos de 10 columnas...

 01110011  01101111  01101101
 01100101  00100000  01100100
 01100001  01110100  01100001
 00001010

...cut s todo menos bytes 2-9,12-19,22-29 ...

011100110110111101101101
011001010010000001100100
011000010111010001100001
00001010

...y tr traduce y ceros a A y unos a B ...

ABBBAABBABBABBBBABBABBAB
ABBAABABAABAAAAAABBAABAA
ABBAAAABABBBABAAABBAAAAB
AAAABABAAAAAAAAAAAAAAAAA

Puede ver en la última línea mi motivación principal para incluir expand - es un filtro tan liviano, y asegura muy fácilmente que cada secuencia escrita, incluso la última, se rellene a 24 bits codificados. Cuando se invierte el proceso y las cadenas se decodifican a -B yte-value, hay dos NUL adjuntos:

ABdc -B <<\IN | od -tc
ABBBAABBABBABBBBABBABBAB
ABBAABABAABAAAAAABBAABAA
ABBAAAABABBBABAAABBAAAAB
AAAABABAAAAAAAAAAAAAAAAA
IN

...como puedes ver...

0000000   s   o   m   e       d   a   t   a  \n  \0  \0
0000014

datos del mundo real

Jugué con él y lo probé con algunas transmisiones simples y realistas. Construí esta canalización elaborada para informes organizados...

{                            ###dunno why, but I often use man man
    (                        ###as a test input source
        {   man man       |  ###streamed to tee
            tee /dev/fd/3 |  ###branched to stdout
            wc -c >&2        ###and to count source bytes
        }   3>&1          |  ###the branch to stdout is here
        ABdc -A           |  ###converted to ABABABA
        tee /dev/fd/3     |  ###branched again
        ABdc -B              ###converted back to bytes
        times >&2            ###the process is timed
    ) | wc -c >&2            ###ABdc -B's output is counted
} 3>&1| wc -c                ###and so is the output of ABdc -A

Sin embargo, aquí no tengo ninguna buena base para comparar el rendimiento. Solo puedo decir que fui llevado a esta prueba cuando estaba (quizás ingenuamente) lo suficientemente impresionado como para hacerlo por...

man man | ABdc -A | ABdc -B

...que pintó la pantalla de mi terminal con man La salida de a la misma velocidad perceptible que el comando sin filtrar podría hacer. El resultado de la prueba fue...

37595                       ###source byte count
0m0.000000s 0m0.000000s     ###shell processor time nil
0m0.720000s 0m0.250000s     ###shell children's total user, system time
37596                       ###ABdc -B output byte count
313300                      ###ABdc -A output byte count

pruebas iniciales

El resto es solo una prueba de concepto más simple de que funciona...

printf %s ABBBAAAABBBBBABBABBBABBB|
tee - - - - - - - -|
tee - - - - - - - - - - - - - - - |
{   printf '2i[q]sq[?z0=qPl?x]s?l?x'
    tr -dc AB | tr AB 01 | fold -b24
} | dc        | od -tx1
0000000 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000020 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000040 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000060 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000100 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000120 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000140 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000160 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000200 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000220 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000240 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000260 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000300 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000320 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000340 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000360 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000400 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000420 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000440 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000460 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000500 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000520 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000540 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000560 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000600 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70
0000620 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb
0000640 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77 70 fb 77
0000660


Linux
  1. ¿Cómo puedo convertir CentOS a CloudLinux OS?

  2. ¿Cómo podemos almacenar una contraseña que no sea texto sin formato?

  3. Cómo distinguir binarios de archivos de texto en Linux

  4. ¿Cómo puedo convertir un puntero de archivo ( FILE* fp ) en un descriptor de archivo (int fd)?

  5. Convierta datos binarios a hexadecimales en un script de shell

Cómo mostrar datos de un archivo de texto en Linux

Bash scripting:cómo escribir datos en archivos de texto

Bash scripting:cómo leer datos de archivos de texto

Cómo convertir un documento de texto a voz en Ubuntu usando eSpeak

¿Cómo puedo ejecutar un ejecutable que no es de confianza en Linux de forma segura?

¿Cómo puedo rasterizar todo el texto en un PDF?