GNU/Linux >> Linux の 問題 >  >> Linux

2 値のテキスト データをバイナリ (ビット表現) に変換するにはどうすればよいですか?

別のパール:

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

証明:

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

上記は、入力を一度に 1 行ずつ読み取ります。行が本来あるべきものであることを確認するのはあなた次第です。

編集: 逆の操作:

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

これにより、一度に 1 バイトの入力が読み取られます。

編集 2: より簡単なリバース操作:

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

上記は STDIN から一度に 3 バイトを読み取ります (ただし EOF を受信 シーケンスの途中であっても致命的な問題ではありません)。


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

次のステートメントを作成する際に、@lcd047 は、私の以前の混乱状態をかなりうまく説明しています:

<ブロック引用>

od の出力に混乱しているようです . od -tx1 を使用 バイトを見る。 od -x ワードを読み取り、バイトをスワップするリトル エンディアン マシン上で。私は上記のやり取りを厳密には追っていませんでしたが、あなたの最初のバージョンは正しかったと思います。バイト オーダーをいじる必要はまったくありません。 od -tx1 を使用するだけです 、 od -x ではありません .

これでたくさん感じます より良い - dd conv=swab の以前の必要性 一日中私を悩ませていました。ピン留めできませんでしたが、何か問題があることはわかっていました。私自身の愚かさでそれを説明できることは、非常に慰めになります - 特に私が何かを学んだので.

とにかく、それは [AB] ではないすべてのバイトを削除します 、次に tr それらを [01] に変換します したがって、fold の前に 結果のストリームを 1 行あたり 24 バイトで処理します。 dc ? 一度に 1 行ずつ読み取り、入力に何かが含まれているかどうかを確認し、含まれている場合は P その数値のバイト値を stdout に出力します。

man dc から :

  • P

    • スタックの一番上にある値を取り出します。文字列の場合は、末尾の改行なしで単純に出力されます。それ以外の場合は数値であり、その絶対値の整数部分は "基数 (UCHAR_MAX+1) として出力されます )" バイトストリーム。
  • i

    • スタックの一番上から値をポップし、それを使用して入力基数を設定します。

一部のシェル自動化

上記に基づいて私が書いたシェル関数を次に示します。これは両方の方法で実行できます:

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
)

ABABABA を変換します -B でバイトに詰め込む 、だからあなたはただ行うことができます:

ABdc -B <infile

ただし、任意の入力は 24 ABABABA に変換されます バイト単位でエンコードされた文字列 - たとえば質問で提示されたものと同じ形式 - w/ -B .

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

AABBAAABAAAABABAAABBAABA
AAAABABAAABBAABBAAAABABA
AABBABAAAAAABABAAABBABAB
AAAABABAAAAAAAAAAAAAAAAA
1
2
3
4
5

-A の場合 出力 cut で転がりました 、 expand 、および od これについてはすぐに説明しますが、別の dc も追加しました .行ごとの ? を削除しました dc を読む f で一度に配列を操作する別のメソッドのスクリプト - f を出力するコマンドです ull dc コマンドスタックから標準出力へ。もちろん、 dc なので スタック指向の 後入れ先出し アプリケーションのタイプ、つまり f ull-stack は、入ったのと逆の順序で出てきます。

これは問題かもしれませんが、別の dc を使用しています とにかく o で 出力基数を 100000000 に設定 すべての 0 パディングをできるだけ簡単に処理するためです。相手の 後入れ先出し を読み取ると、 ストリーム、そのロジックをもう一度適用すると、すべてが洗い流されます。 2 つの dc の共同作業は次のようになります:

{   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 

...最初の 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

...毎秒 teedc から書かれたように 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.

...そして、2 番目の dc の出力 書き込みは...

 01110011
 01101111
 01101101
 01100101
 00100000
 01100100
 01100001
 01110100
 01100001
 00001010

そこから関数 paste ...

にあります
 01110011    01101111    01101101
 01100101    00100000    01100100
 01100001    01110100    01100001
 00001010

...expand s を 10 列間隔でスペースに...

 01110011  01101111  01101101
 01100101  00100000  01100100
 01100001  01110100  01100001
 00001010

...cut 2-9,12-19,22-29 バイトを除くすべてを削除します ...

011100110110111101101101
011001010010000001100100
011000010111010001100001
00001010

...そして tr とゼロを A に変換します そして B までのもの ...

ABBBAABBABBABBBBABBABBAB
ABBAABABAABAAAAAABBAABAA
ABBAAAABABBBABAAABBAAAAB
AAAABABAAAAAAAAAAAAAAAAA

expand を含める主な動機は最後の行にあります。 - これは非常に軽量なフィルターであり、書き込まれたすべてのシーケンス (最後のシーケンスも含む) が 24 のエンコードされたビットにパディングされることを非常に簡単に保証します。それが逆のプロセスで、文字列が -B にデコードされる場合 yte-value には、2 つの NUL が追加されています:

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

...ご覧のとおり...

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

現実世界のデータ

私はそれで遊んで、いくつかのシンプルで現実的なストリームで試しました.段階的なレポート用にこの精巧なパイプラインを構築しました...

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

ただし、ここでは、パフォーマンスを比較するための適切な根拠はありません。私がこの試練に駆り立てられたのは、(おそらく素朴に) だったときだけです。 ...

man man | ABdc -A | ABdc -B

... man で端末画面を描画しました の出力は、フィルター処理されていないコマンドと同じ識別可能な速度で行われます。テストの結果は...

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

初期テスト

残りは、それがまったく機能するという、より単純な概念実証です...

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. Linux のシリアル ポートでデータを監視するにはどうすればよいですか?

  2. ファイルデータをプレーンな 16 進数に変換するには?

  3. HTMLをテキストに変換するには?

  1. CentOS を CloudLinux OS に変換するにはどうすればよいですか?

  2. Linux で信頼できない実行可能ファイルを安全に実行するにはどうすればよいですか?

  3. PDF 内のすべてのテキストをラスタライズするにはどうすればよいですか?

  1. プレーンテキスト以外のパスワードを保存するにはどうすればよいですか?

  2. Linuxでテキストファイルからバイナリを見分ける方法

  3. ファイル ポインタ ( FILE* fp ) をファイル記述子 (int fd) に変換するにはどうすればよいですか?