GNU/Linux >> Znalost Linux >  >> Linux

Jak mohu převést dvouhodnotová textová data na binární (bitová reprezentace)

Další perl:

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

Důkaz:

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

Výše uvedené čte vstup jeden řádek po druhém. Je na vás, abyste se ujistili, že čáry jsou přesně takové, jaké mají být.

Upravit: Opačná operace:

#!/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 );

Toto čte bajt vstupu najednou.

Úprava 2: Jednodušší zpětná operace:

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

Výše uvedené čte 3 bajty najednou od STDIN (ale přijímá EOF uprostřed sekvence není fatální problém).


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

Následujícím prohlášením @lcd047 docela dobře vyřešil můj dřívější stav zmatku:

Zdá se, že jste zmateni výstupem od . Použijte od -tx1 podívat se na bajty. od -x čte slova a na počítačích little endian, které vyměňují bajty. Nesledoval jsem pozorně výše uvedenou výměnu, ale myslím, že vaše původní verze byla správná a nemusíte si vůbec zahrávat s pořadím bajtů. Stačí použít od -tx1 , nikoli od -x .

Teď se díky tomu cítím hodně lepší - dřívější potřeba dd conv=swab otravoval mě celý den. Nemohl jsem to připnout, ale věděl jsem, že s tím není něco v pořádku. Být schopen vysvětlit to ve své vlastní hlouposti je velmi uklidňující - zvláště když jsem se něco naučil.

Každopádně to smaže každý bajt, který není [AB] a poté tr přeložte je na [01] podle toho před fold ing výsledného datového proudu o velikosti 24 bajtů na řádek. dc ? čte řádek po řádku, kontroluje, zda vstup něco obsahoval, a pokud ano, P vypíše bajtovou hodnotu tohoto čísla do stdout.

Od man dc :

  • P

    • Vysune hodnotu v horní části zásobníku. Pokud se jedná o řetězec, vytiskne se jednoduše bez konce nového řádku. Jinak je to číslo a celá část jeho absolutní hodnoty se vytiskne jako "základ (UCHAR_MAX+1 )" byte stream.
  • i

    • Vytáhne hodnotu z horní části zásobníku a použije ji k nastavení vstupního radixu.

nějaká automatizace prostředí

Zde je funkce shellu, kterou jsem napsal na základě výše uvedeného, ​​která může jít oběma způsoby:

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
)

Tím se přeloží ABABABA do bajtů s -B , takže můžete udělat:

ABdc -B <infile

Ale přeloží libovolný vstup na 24 ABABABA bit-per-byte zakódované řetězce - ve stejné podobě, jaká je uvedena například v otázce - w/ -B .

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

AABBAAABAAAABABAAABBAABA
AAAABABAAABBAABBAAAABABA
AABBABAAAAAABABAAABBABAB
AAAABABAAAAAAAAAAAAAAAAA
1
2
3
4
5

Pro -A výstup jsem vložil do cut , expand a od zde, do kterého se pustím za chvíli, ale přidal jsem také další dc . Vypustil jsem řádek po řádku ? přečtěte si dc skript pro jinou metodu, která pracuje s polem v čase s f - což je příkaz, který vypíše f ull dc příkazový zásobník na stdout. Samozřejmě, protože dc je zásobník orientovaný poslední dovnitř, první ven typ aplikace, to znamená, že f ull-stack vychází v opačném pořadí, v jakém byl vložen.

To může být problém, ale já používám jiný dc každopádně s o utput radix nastaven na 100000000 zvládnout všechny nulové výplně co nejjednodušeji. A když přečte poslední dovnitř, první ven toho druhého stream, znovu na to platí tu logiku a všechno to vyjde v pračce. Dva dc funguje na koncertě takto:

{   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 

...stream za prvních 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

...za druhý tee , jak je napsáno z dc na 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.

...a výstup, který druhý dc píše je...

 01110011
 01101111
 01101101
 01100101
 00100000
 01100100
 01100001
 01110100
 01100001
 00001010

Odtud funkce paste je to na ...

 01110011    01101111    01101101
 01100101    00100000    01100100
 01100001    01110100    01100001
 00001010

...expand s do mezer v intervalech 10 sloupců...

 01110011  01101111  01101101
 01100101  00100000  01100100
 01100001  01110100  01100001
 00001010

...cut s pryč všechny kromě bajtů 2-9,12-19,22-29 ...

011100110110111101101101
011001010010000001100100
011000010111010001100001
00001010

...a tr převede a nuly na A a jedničky na B ...

ABBBAABBABBABBBBABBABBAB
ABBAABABAABAAAAAABBAABAA
ABBAAAABABBBABAAABBAAAAB
AAAABABAAAAAAAAAAAAAAAAA

Na posledním řádku můžete vidět moji hlavní motivaci pro zařazení expand - je to takový lehký filtr a velmi snadno zajišťuje, že každá zapsaná sekvence - i ta poslední - je doplněna na 24 kódovaných bitů. Když je proces obrácený a řetězce jsou dekódovány na -B yte-value, jsou připojeny dvě hodnoty NUL:

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

...jak vidíte...

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

údaje ze skutečného světa

Hrál jsem si s tím a zkusil to s několika jednoduchými, realistickými streamy. Vytvořil jsem tento propracovaný kanál pro postupné zprávy...

{                            ###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

Zde však nemám žádný dobrý základ pro srovnání výkonu. Mohu jen říci, že jsem byl k tomuto testu přiveden, když jsem byl (možná naivně) natolik ohromen, že to udělal...

man man | ABdc -A | ABdc -B

...což nakreslilo obrazovku mého terminálu s man výstup 's stejnou rozpoznatelnou rychlostí, jakou by mohl dělat nefiltrovaný příkaz. Výstup testu byl...

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

počáteční testy

Zbytek je jen jednodušším důkazem konceptu, že to vůbec funguje...

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. Jak můžeme uložit jiné heslo než prostý text?

  2. Jak rozeznat binární soubory od textových souborů v linuxu

  3. Jak mohu převést ukazatel na soubor ( FILE* fp ) na deskriptor souboru (int fd)?

  1. Převeďte binární data na hexadecimální ve skriptu shellu

  2. Jak mohu převést mezery na karty ve Vimu nebo Linuxu?

  3. Jak mohu ospravedlnit prostý text v Linuxu?

  1. Jak mohu převést CentOS na CloudLinux OS?

  2. převést textový soubor bitů na binární soubor

  3. Jak mohu rastrovat veškerý text v PDF?