ストリームでゼロを1に、またはその逆に置き換える最速の方法は何ですか?

ストリームでゼロを1に、またはその逆に置き換える最速の方法は何ですか?

0sとsで構成される文字列が与えられた場合、1私の目標は0を1に変更するか、その逆に置き換えることです。例:

入力する

111111100000000000000

期待される出力

000000011111111111111

sed私は成功せずに次のコマンドを試しました

echo '111111100000000000000' | sed -e 's/0/1/g ; s/1/0/g'
000000000000000000000

私は何を見逃していますか?

答え1

あなたはそれを使用することができますtrこの目的の主な目的は文字翻訳です。

echo 111111100000000000000 | tr 01 10

コマンドsedは、すべての0を1に置き換えて1のみを含む文字列(元の1とすべて置き換えられた0)を生成し、すべての1を0に置き換えて0のみを含む文字列を生成します。

長いストリームでは、100MiBファイルよりtrも高速です。sed

$ time tr 10 01 < bigfileof01s > /dev/null
tr 10 01 < bigfileof01s > /dev/null  0.07s user 0.03s system 98% cpu 0.100 total

$ time sed y/10/01/ < bigfileof01s > /dev/null
sed y/10/01/ < bigfileof01s > /dev/null  3.91s user 0.11s system 99% cpu 4.036 total

答え2

しかし、tr仕事に適したツールですsedy(代替)コマンドの代わりに(翻訳)コマンドを使用してこれを実行できますs

$ echo '111111100000000000000' | sed 'y/01/10/'
000000011111111111111

y基本的に -sedの内部実装trとそれに伴うすべてのオーバーヘッドです。

答え3

一つの方法はecho "111111100000000000000" | sed 's/1/2/g;s/0/1/g;s/2/0/g'

答え4

文字列が 1 行だけで 0 と 1 で構成されている場合は、次のようになります。

echo "111111100000000000000" |
    perl -e 'while (read(STDIN, $b, 1)) { print chr(ord($b) ^ 1); } print "\n";'

文字列に複数の行を含めることができる場合は、バイトの読み取り方法を変更して変更します(perl -eファイルハンドルが必要なので)。perl -neread

echo -e "111111100000000000000\n0001111010101" |
    perl -ne 'while (/(.)/g) { print chr(ord($1)^1) } print "\n"'

ただし、これは各行を文字列に分割するため、大容量ファイルではそれほど効率的ではない可能性があります。この場合、いくつかの確認が必要です。

echo "122111111034000000000abc0000" | perl -e 'while (read(STDIN, $b, 1)) {
    print ($b eq '0' or $b eq '1' ? chr(ord($b) ^ 1) : $b) } print "\n";'

ご覧のとおり、この方法は'0'および他の文字を含む文字列にも適用されます。'1'

関連情報