別のパール:
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
...毎秒 tee
、 dc
から書かれたように 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
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