/dev/urandomのストリームを使用して指定された数の行でファイルを埋めるには?

/dev/urandomのストリームを使用して指定された数の行でファイルを埋めるには?

ユーザーが定義した行数と1行あたりの文字数を使用して、0と1のランダムなシーケンスでファイルを埋めようとします。

最初のステップは、0と1のランダムストリームを取得することです。

cat /dev/urandom | tr -dc 01

次に、このストリームでファイルを埋めようとします(そしてCtrl + Cを介して塗りつぶしプロセスを終了します)。

cat /dev/urandom | tr -dc 01 > foo

このように生成されたfooファイルの行数を数えてみると、0行が出ます。

cat foo | wc -l
0

これでフローを制御したいので、名前付きパイプを作成し、その中にフローを指定します。次に、1行当たりの文字数とファイルの行数を制御したい無駄な希望で、ddコマンドを使用して名前付きパイプに接続しました。

makefifo namedpipe
cat /dev/urandom | tr -dc 01 > namedpipe
dd if=namedpipe of=foo bs=10 count=5

fooファイルは実際には50バイトの0と1で埋められていますが、行数はまだ0です。

この問題をどのように解決しますか?ファイル内の各文字数に改行文字を挿入する必要があるようですが、その場合はどうすればよいかわかりません。

答え1

どうですかfold? coreutilsの一部です...

$ tr -dc 01 < /dev/urandom | fold -w 30 | head -n 5
001010000111110001100101101101
000101110011011100100101111000
111010101011100101010110111001
111011000000000101111110110100
110011010111001110011010100011

または使用できない場合は、次のものを使用できますawk

$ tr -dc 01 < /dev/urandom | awk \$0=RT RS=.\{,30} | head -n 5
000100010010001110100110100111
101010010100100110111010001110
100011100101001010111101001111
010010100111100101101100010100
001101100000101001111011011000

またはループで何かをすることができます...

$ for line in $(seq 1 5)
> do
>     echo $(tr -dc 01 < /dev/urandom | head -c 30)
> done
100101100111011110010010100000
000000010000010010110111101011
010000111110010010000000010100
001110110001111011101011001001
001010111011000111110001100110

他の方法があると確信しています...カスタムフォーマットを使用するhexdumpを使用すると可能だと思いましたが、明らかにそうではありませんでした... ;)

答え2

LC_ALL=C </dev/urandom \
tr '\0-\377' '[0*128][1*]' |
dd ibs=50 cbs=10 conv=unblock count=1

これはすべての入力ASCIIバイトを変換します(指定どおりにすべてのバイトになりますLC_ALL=C一様に分布した0または1のいずれかに変換されます。\0との間の最初の128バイトは\1770から1に変換されます\200-\377。したがって、すべての入力バイトを使用しながら、1または0のみを含むランダムなシーケンスのシーケンスを出力できます。

選択は正確ですが、5つの11バイトの出力行を取得するためにブロックサイズをdd設定する必要はありません。bs=(10\n行以上)彫刻。代わりにcount=1、入力バイトブロックにシングルバイトを指定し、それを5つのサイズ変換ブロックに分割し、すべての末尾のスペースを削除してから、各変換ブロックにewlineを追加してcbsサイズで編集する必要があります。read()ibs=50cbs=10conv=unblock\n(あなたは..しなかった)

だから実行してみると次のように印刷されました。

1101001010
1100001001
1101110100
1011011000
1011110100
1+0 records in
0+1 records out
55 bytes (55 B) copied, 0.00176591 s, 31.1 kB/s

ddまた、ある方法と他の方法との間の速度比較を示し、書き込みユーティリティのバッファサイズのブロック要素を読み取る場合は、パイプから読み取ることが問題にならないことを示すために分担金を少し上げました。だからまず私は次のことをしました。

time (
LC_ALL=C </dev/urandom \
tr -dc 01 |
dd ibs=4k cbs=10 conv=unblock count=k|
grep \[^01])

...標準出力に出力なし(したがって、grep0または1以外の一致はありません)stderrに以下を表示します。

1024+0 records in
9011+1 records out
4613735 bytes (4.6 MB) copied, 25.8898 s, 178 kB/s
( LC_ALL=C tr -dc 01 < /dev/urandom |\
  dd ibs=4k cbs=10 conv=unblock count=k |...)\
0.80s user 25.42s system 101% cpu 25.921 total

上記の情報を見ると、パイプラインがシステムコールを待つのに25.5秒かかったことがわかります。いいですが、dd4096バイトの入力レコードのうち1024をすべて読むことも教えてくれます。完全そして、read()早期返却のために切れた部分はありません。これはtr、バッファが4kチャンクからパイプアウトされるためです。

とにかく、以下は別の方法で実行するか、スペクトラム拡散のすべてのランダム入力を変換することです。

time (
LC_ALL=C </dev/urandom \
tr '\0-\377' '[0*128][1*]' |
dd ibs=4k cbs=10 conv=unblock count=k|
grep '[^01]')

もう一度言いますが、標準出力には何もありません。みんな出力はdd0、1、または改行のいずれかです。これはstderrにあります。

1024+0 records in
9011+1 records out
4613735 bytes (4.6 MB) copied, 0.554202 s, 8.3 MB/s
( LC_ALL=C tr '\0-\377' '[0*128][1*]' \
  < /dev/urandom|dd ibs=4k cbs=10 ...)\
0.61s user 0.36s system 171% cpu 0.571 total

...これは、dd全入力レコード1024個+切り捨てられた入力レコード0個を読み取ることを再び示していますが、処理時間は大きく異なります。ここで実際に別々のコアで並列に、まとめて作業できることは、プロセス全体が0.6秒以内に完了するのにかかる時間よりも時間がかかりましたtrddこれはより速いでしょう。

答え3

作成中に改行を追加するには:

{ process-without-terminating-newline ; echo ;} > outfile

既存のファイルに追加するには:

echo >> outfile

答え4

次に、このストリームでファイルを埋めようとします(そしてCtrl + Cを介して塗りつぶしプロセスを終了します)。

cat /dev/urandom | tr -dc 01 > foo

このように生成されたfooファイルの行数を数えてみると、0行が出ます。

cat foo | wc -l
0

cat両方tr バッファー彼らの出力。Ctrl+を押すと、Cコマンドバッファに残っているすべてのデータが失われます。バッファ値全体が蓄積される前にプログラムを非常に早く中断したtrので、何も書きませんでした。

dd文字デバイスやパイプからの読み込みには使用しないでください。

headLinuxでは、特定のバイト数以降のデータの切り捨てを使用できます。

i=0
while [ "$i" -lt "$number_of_lines" ]; do
  </dev/urandom tr -dc 01 | head -c "$bits_per_line"; echo
  i=$((i+1))
done >foo

または、必要なバイト数を作成し、それを使用してfold改行を挿入します。

</dev/urandom tr -dc 01 |
fold -w "$bits_per_line" |
head -n "$number_of_lines"

遅くないか非常に遅いすべてのバイトを拒否します01入力の127/128を拒否します。基本2出力を生成する標準ユーティリティはありませんが、これを使用してod16進数を生成してビット単位に変換できます。

</dev/urandom od -An -tx1 |
sed 's/ //g; s/0/@@@@/g; s/1/@@@`/g; s/2/@@`@/g; s/3/@@``/g; s/4/@`@@/g; s/5/@`@`/g; s/6/@``@/g; s/7/@```/g; s/8/`@@@/g; s/9/`@@`/g; s/[Aa]/`@`@/g; s/[Bb]/`@``/g; s/[Cc]/``@@/g; s/[Dd]/``@`/g; s/[Ee]/```@/g; s/[Ff]/````/g; y/@`/01/' |
fold -w "$bits_per_line" |
head -n "$number_of_lines"

その場合は、xxdこれを使用してバイトをbase-2表現に変換できます。 1行あたりの桁数が8の倍数の場合は、必要に応じて改行を-c挿入して数行-l後に停止するようにオプションを使用することもできます。

</dev/urandom xxd -b -c "$bytes_per_line" -l "$((bytes_per_line * number_of_lines))" |
sed -e 's/  .*//' -e 's/.*://'

関連情報